*Tämä artikkeli käsittelee tietokoneohjelmointia. Katso Assembly sanan muista merkityksistä.*
Motorola 6800 8-bittisen suorittimen assembly-kielellä kirjoitetun koodin käännöslistausta.
**Assembly** (usein virheellisesti *assembler*) on tietokoneen ohjelmointikieli, joka koostuu symbolisesta vastineesta tietylle konekielelle. Toinen nimitys assembly-kielelle on *symbolinen konekieli*. Eri prosessori-tyyppejä käyttäville tietokoneille tarvitaan eri assembly-kieli.

Assembly on matalan tason kieli, jota sanotaan myös toisen sukupolven ohjelmointikieleksi. Kieli on isomorfinen ja vastaa läheisesti konekieltä: kielen ominaisuudet ovat yksi-yhteen tai yksi-moneen suhteessa käskykannan ominaisuuksiin. Ylemmän tason kielet käyttävät ei-isomorfista muunnosta.

Konekieli on suorittimen tai vastaavan laitteen ymmärtämä kieli.
Konekielen käskyt ovat lukujonoja, ja siksi vaikeita muistaa sekä hahmottaa koodia kirjoitettaessa. Siksi konekielen kirjoittamisen sijaan käytetään yleensä assemblyä. Assembly-ohjelma muutetaan konekieliseksi assembler-kääntäjällä.

Assembly-ohjelma koostuu käskyistä (engl. *mnemonics*) ja niihin liittyvät operandeista, jotka vastaavat konekielen käskyjä. Lisäksi assembly-kielisessä ohjelmassa on muistiosoitteiden nimiä ja muita apusanoja.

Assemblyn käytön varjopuolia verrattuna C:n tyyppisiin korkean tason kieliin ovat muun muassa ohjelmoinnin vaikeus, hitaus ja virhealttius. Assemblyn käyttö vaatii taitoa ja erityistä tarkkuutta.

Assembly-kieli on huonosti siirrettävä kieli eri prosessoreiden välillä. Eri prosessorityypeille on erilaiset assembly-ohjelmat, elleivät prosessorit ole keskenään yhteensopivia. Assemblyä vaivaa myös assembler-kääntäjien erilaisuus henkilökohtaisille tietokoneille.*lähde?* Eri valmistajien tekemät assembly-kääntäjät saattavat erota toisistaan huomattavasti, vaikka prosessori olisikin sama.

Assemblyn vahvin puoli on sillä tuotetun ohjelman nopeus, mikäli ohjelmoija osaa optimoida koodin ylemmän tason kielen kääntäjiä paremmin. Assembly on myös melko helppo oppia *kenen mukaan?*, koska sen käskyt ovat melko yksinkertaisia.

Historia
--------

Small-Scale Experimental Machine (SSEM) oli ensimmäinen tallennetun ohjelman tietokone, jossa ohjelma voitiin tallettaa tietokoneen muistiin ja ohjelma voitiin ladata ilman fyysisiä muutoksia laitteeseen. 
Konekieli oli koneelle tehokasta käsitellä, mutta ei ihmisille: aluksi tämä ei ollut ongelma koska ohjelmoijat olivat samoja henkilöitä jotka suunnittelivat koneen mutta uusien ohjelmoijien tarpeen kasvaessa laitteiston yksityiskohtien kuvaileminen tuli ongelmaksi. Lisäämällä muistisääntöjä (engl. *mnemonics*) ohjelmoijan työtä helpotettiin. Muistisääntöjen muuttaminen konekielisiin oli alkuun käsityötä ennen assembler-ohjelman kehittämistä. 
Varhaisen assembly-kielen kehitti Kathleen Booth Automatic Relay Calculatorille.
Termin *assembler* yleistymiseen liitetään Wilkesin, Wheelerin ja Gillin kirja *The preparation of programs for a digital computer* (1951).
Ennen vuotta 1954 lähes kaikki ohjelmointi tehtiin matalan tason ohjelmointikielillä kuten konekielellä tai assemblyllä.

Assembly, symbolinen konekieli
------------------------------

Apple II:n konekieltä ja assembleria. Ensimmäinen sarake: muistiosoitteita. Seuraava sarakeryhmä: konekieltä heksadesimaalina.
Viimeiset kaksi saraketta: Assembly-kieltä. 3. sarake: käsky, 4. sarake: operandit.
Assembly on ohjelmointikielten alaluokka ja tarkoittaa symbolisia konekieliä. Tietokoneiden ymmärtämät konekielet koostuvat yleensä binäärimuotoisista käskyistä, jotka voidaan esittää esimerkiksi 1- ja 0-merkkien sarjoina.

Eräs Intelin 8086 suorittimen konekielen käsky siirtää luvun 97 rekisteriin AL:

```
 10110000 01100001

```

Monesti tämä esitetään heksadesimaalilukuna lyhyemmän esitysmuodon vuoksi:

```
 B0 61

```

Assemblyllä käsky näyttää vielä selkeämmältä:

```
MOV AL, 61h ; Kommentti: Siirrä AL-rekisteriin luku 97 , mikä on heksadesimaalilukuna 61 h (61 hex)

```

Esimerkissä "MOV" on käsky ja 61h operandi. Kyseistä syntaksia käytetään esimerkiksi MASM:issa, jossa operandit ovat järjestyksessä *kohde, lähde* eli "al, 61h"

GNU Assemblerissa (GAS) käytetyllä AT&T:n syntaksilla operandit ovat järjestyksessä *lähde, kohde*.

```
 movb $0x61, %al

```

Symbolinen konekieli on konekielen havainnollisempi ja ihmisläheisempi esitysmuoto, joka määrittelee konekielen käskyille kirjoitetun kielen kaltaisen ulkoasun. Assembly-kielessä on siten lähes sama rakenne ja komennot kuin varsinaisessa konekielessä, mutta tekstimuotoisuus helpottaa ohjelman kirjoittamista ja ymmärtämistä. Lisäksi eri muistiosoitteisiin viitataan assemblyssa usein nimin ja itse muistiosoite voidaan antaa assemblerin määriteltäväksi. Konekieli ja siis myös assembly ovat sidonnaisia tiettyyn suoritinperheeseen.

Assembly-kielinen ohjelma muutetaan konekielelle assembleriksi nimetyllä kääntäjällä. Samaa laiteympäristöä varten voi olla useita eri syntakseja riippuen käytetystä assembler-ohjelmasta (esimerkiksi MASM, GAS). Muilla suorittimilla on omat eronsa ja ohjelmansa.

Esimerkiksi 32-bittisen kokonaisluvun, jonka arvo on "5" siirtäminen datarekisteriin `d0` Motorola 68000 -sarjan suorittimella:

```
 move.l    #5, d0

```

Inline-assembly
---------------

Assembleria on käytetty monesti korkean tason kielten ohella nopeuttamaan ohjelman ajoa joissain kohdissa.

Korkean tason kielen kääntäjät, esimerkiksi GCC, osaavat kääntää ns. inline-assemblyä, joka on korkeamman tason kielen joukossa olevia assembly-käskyjä.

Esimerkki C-kielen joukossa `asm`-lausekkeella:

```
int src = 1;
int dst; 

asm ("mov %1, %0\n\t"
 "add $1, %0"
 : "=r" (dst) 
 : "r" (src));

printf("%d\n", dst);

```

Eri kääntäjien tuki inline-assemblylle vaihtelee mutta muun muassa LLVM/Clang on pitkälti yhteensopiva GCC:n kanssa.

Assemblyn käyttökohteet
-----------------------

Assembly antaa ohjelmoijalle täyden määräysvallan suorittimelle syötettävän komentosarjan suhteen, ja siksi sitä käyttämällä voidaan hyödyntää tietokoneen resurssit tehokkaasti. Assemblyä käytettiin kotimikrojen alkuaikoina melko yleisesti. Esimerkiksi MS-DOS-käyttöjärjestelmä, taulukkolaskentaohjelma Lotus 1-2-3 ja useimmat 16-bittisen sukupolven tietokoneiden pelit ohjelmoitiin assemblyllä. Varsinaisen assembly-kielen käyttö 8-bittisillä tietokoneilla (kuten Commodore 64, MSX, ZX Spectrum) on useimmiten liian raskasta. Sen sijaan joko käytettiin konekielimonitoreja tai hyödynnettiin ristiinkääntämistä kirjoittamalla assemblyä ensin PC:llä tai UNIX-työasemalla ja ristiinkääntämällä se lopulliselle kohteelleen.

Puhtaan assembly-kielen käyttöä on perinteisesti puoltanut ohjelmakoodin tiiviys verrattuna kääntäjien tuottamaan konekieleen. Etenkin varhaisten tietokoneiden muistit ovat olleet verrattain pieniä ja asettaneet tiukan rajan suoritettavan ohjelman koolle. Assembly-kielellä toteutettuun ohjelmaan voitiin koodata vain sovelluksen tarvitsemat toiminnot, kun taas esimerkiksi FORTRAN- tai ALGOL-kielellä toteutetut ohjelmat toivat aina mukanaan ylimääräistä koodia; tyypillisesti suoraan assemblyllä toteutettu ohjelma oli kooltaan vain 1/10 korkean tason kielellä tuotetusta ohjelmasta. Kokoedun takia esimerkiksi kiintolevyn alussa oleva käynnistyskoodi kirjoitetaan nykyäänkin assemblyllä.

Sovellusohjelmien osalta tällainen optimointi ei kuitenkaan yleensä enää ole mielekästä, eikä assemblyä juurikaan käytetä nykyaikaisten henkilökohtaisten tietokoneiden kaltaisten koneiden eikä myöskään älypuhelimien sovellusohjelmoinnissa. Sovellusohjelmat ovat niin isoja, ettei niitä voi mielekkäästi hallita assembly-tasolla. Suorittimet ovat myös niin tehokkaita, että koodin nopeutuksella saatava hyöty ei yleensä ole vaivan arvoista. Pullonkaulat ovat yleensä muualla, kuten I/O-operaatioiden ja sivutuksen aiheuttamassa viiveessä. Korkean tason ohjelmointikielten kääntäjät ovat myös kehittyneet, ja samalla suorittimet sisäiseltä toiminnaltaan monimutkaistuneet niin, että kääntäjä tuottaa useimmiten tehokkaampaa koodia kuin mitä käsin ohjelmoimalla voisi saada aikaan, varsinkaan kohtuullisella työmäärällä. Lisäksi esimerkiksi tehokkaiden algoritmien ja tietorakenteiden valinta saattaa suurempia kokonaisuuksia assemblyllä koodattaessa jäädä pahasti taka-alalle, koska niiden toteuttaminen voi olla konekielellä liian työlästä.

Sulautettujen järjestelmien ohjelmoinnissa on assemblyllä jonkin verran vahvempi asema kuin ohjelmoinnissa henkilökohtaisille tietokoneille. Kokonaisia ohjelmia ei silti näillekään järjestelmille ole mielekästä ohjelmoida pelkällä assemblyllä.

Erityistilanteissa assemblyllä on kuitenkin vielä tärkeä asema. Sitä voi tarvita laitteistoläheistä ohjelmointia vaativissa tehtävissä, kuten laiteohjainten kehityksessä. Vielä toisinaan assemblyllä on käyttöä myös tehokkuutta vaativissa sovelluksissa, kuten salauksessa tai videon koodauksessa, kun ohjelman osia optimoidaan. Näissäkin tapauksissa assemblyllä koodataan mahdollisimman pieni osa. Kääntäjän tuottamaa assembly-koodia analysoimalla voidaan löytää keinoja korjata korkeamman tason koodia ja kääntäjälle annettavia ohjeita, kunnes tulos on haluttu. Koodin ymmärtäminen assembly-tasolla on joskus tärkeää myös vianetsinnässä.

Assembly-esimerkkejä
--------------------

### Tekstin tulostaminen MS-DOS -käyttöjärjestelmällä

Alla on esimerkki Assembly-kielisestä ohjelmasta Intelin x86-suvun arkkitehtuureille. Ohjelmakoodissa on käytetty Intelin x86-merkintätapaa. Ohjelma on MS-DOS-käyttöjärjestelmässä suoritettava COM-tyyppinen ohjelma.

```
1  org 100h
2  section .text
3
4         mov ah,9h
5         mov dx,offset teksti
6         int 21h
7         ret
8
9 teksti: db 'Hei maailma!$'
```

Ohjelma kutsuu MS-DOS -käyttöjärjestelmän järjestelmäkutsua, joka tulostaa annetussa muistiosoitteessa olevan tekstin "Hei maailma!".
Rivien toiminta:

* Rivi 1 määrittelee ohjelman alkuosoitteen segmenttinsä sisällä. Com-tyyppisissä ohjelmissa alkuosoite on aina 100h.
* Rivi 2 ilmoittaa kääntäjälle, minkä tyyppistä aineistoa tässä kappaleessa on.
* Rivi 4: heksaluku 9 siirretään rekisteriin AH.
* Rivi 5: rekisteriin DX siirretään muistipaikan *teksti* osoite.
* Rivi 6: Tulostamiseen käytetään PC:n DOS-käyttöjärjestelmien ohjelmistokeskeytystä 21h (h tarkoittaa heksalukua, luku on desimaalisena 33), jolle halutun toiminnon numero (9) annetaan rekisterissä AH. Rekisterissä DX on muistiosoite, josta haluttu $-merkkiin loppuva teksti alkaa datasegmentin ds sisällä.
* Rivi 7: Rutiinin suorittamisen jälkeen palataan pääohjelmaan, mikä onnistuu com-tyyppisessä ohjelmassa pelkällä ret-käskyllä. Muuntyyppisessä ohjelmassa voi olla tarpeen käyttää ohjelmistokeskeytyksen 21h alaista toimintoa 4Ch.
* Rivi 9: Tekstiin kuuluvat tavut on määritelty rivillä 9, joten ne alkavat heti ohjelmakoodin viimeisen tavun jälkeen. Tekstin alkuosoitteelle on annettu nimi (osoite) *teksti*. Lopussa oleva dollarin merkki päättää tulostuksen.

Yllä olevaa ohjelmaa vastaava ohjelma ylemmän tason kielellä, tässä Pascal-ohjelma on

```
program Hello;
begin
 writeln( 'Hello World' );
end.

```

### Fibonaccin lukujen laskeminen

Seuraava esimerkki on Fibonaccin lukujen laskija Motorola 68000 -sarjan suorittimille. Lasketaan {\displaystyle n}:s Fibonaccin luku antamalla {\displaystyle n} rekisterissä d0. Fibonaccin {\displaystyle n:s} luku {\displaystyle f\_{n}} lasketaan silmukassa kaavalla: {\displaystyle f\_{n}=f\_{n-1}+f\_{n-2}}, ja {\displaystyle f\_{0}=1} ja {\displaystyle f\_{1}=1}.

```
 1  **fibonacci**:      cmp.l #1,d0
 2                  bgt.b **overone**
 3                  moveq #1,d0
 4                  rts
 5  **overone**:        moveq #1,d1
 6                  moveq #1,d2
 7                  moveq #1,d3
 8  **loop**:           move.l d2,d4
 9                  add.l  d3,d4
10                  move.l d3,d2
11                  move.l d4,d3
12                  addq.l #1,d1
13                  cmp.l  d0,d1
14                  bne.b  **loop**
15                  move.l d4,d0
16                  rts
```

Riveillä 1-4 tarkistetaan, onko d0 {\displaystyle \leq } 1, ja jos se on, lopetetaan aliohjelma ja palautetaan tuloksena 1. Rivillä 5 asetetaan silmukkalaskuri rekisterissä d1 arvoon 1. Riveillä 6 ja 7 asetetaan rekisterit d2 ja d3 arvoihin {\displaystyle f\_{0}} ja {\displaystyle f\_{1}}. Rivillä 8 alkaa silmukka. Rivit 8 ja 9 laskevat seuraavan Fibonaccin luvun rekisteriin d4 summaamalla kaksi edellistä lukua rekistereistä d2 ja d3. Riveillä 10 ja 11 tallennetaan muistiin 2 uusinta Fibonaccin lukua rekistereihin d2 ja d3 seuraavaa kierrosta varten. Rivillä 12 kasvatetaan silmukkalaskuria yhdellä. Riveillä 13 ja 14 vertaillaan silmukkalaskuria ja {\displaystyle n}:ää. Mikäli {\displaystyle n} on saavutettu, lopetetaan silmukka. Muuten hypätään takaisin riville 8. Rivillä 15 siirretään tulos rekisteristä d4 rekisteriin d0, ja rivillä 16 poistutaan aliohjelmasta.

### Esimerkeistä

Esimerkit antavat hyvän kuvan, miksi sovelluksia kehittäessä aikaa kuluu erittäin kauan ja työskentely puhtaalla assemblyllä on hankalaa. Korkeamman tason ohjelmointikielet on luotu helpottamaan tätä työtä, ja kääntäjiä käytetään muuntamaan selkeämpi kieli konekielimuotoon. Konekielet ovat kuitenkin yleensä hyvin suoraviivaisia, ja käskyjen suorittamat toiminnot ovat yksinkertaisia. Tämän vuoksi assembly-ohjelmointi on helppo opetella.

Katso myös
----------

* Luettelo assembler-ohjelmista

Lähteet
-------

1. 1 2  Assembly language *britannica.com*. Viitattu 12.9.2020. (englanniksi)
2. ↑  www.computerhope.com *computerhope.com*. Viitattu 26.7.2017. (englanniksi)
3. 1 2 3  Roger Clarke: A Contingency Approach to the Application Software Generations *rogerclarke.com*.  1991. Viitattu 4.2.2020. (englanniksi)
4. ↑  The Manchester Small Scale Experimental Machine -- "The Baby" *curation.cs.manchester.ac.uk*. Viitattu 25.8.2017.
5. ↑  Guy Fedorkow: About the Computer History Museum’s IBM 1401 Machines *computerhistory.org*.  19.2.2015. Viitattu 28.1.2020. (englanniksi)
6. 1 2 3 4  Harry Fairhead: History of Computer Languages - The Classical Decade, 1950s *i-programmer.info*. Viitattu 13.9.2020. (englanniksi)
7. ↑  Liam Proven: RIP: Kathleen Booth, the inventor of assembly language *theregister.com*.  29.10.2022. Viitattu 30.10.2022. (englanniksi)
8. ↑  John Backus: FORTRAN Session (PDF) Computer History Musem. Viitattu 10.2.2020. (englanniksi)
9. ↑  Linux assemblers: A comparison of GAS and NASM IBM. Viitattu 8.10.2017.
10. ↑  6.47 How to Use Inline Assembly Language in C Code *gcc.gnu.org*. Viitattu 12.9.2020. (englanniksi)
11. ↑  6.47.2 Extended Asm - Assembler Instructions with C Expression Operands *gcc.gnu.org*. Viitattu 12.9.2020. (englanniksi)
12. ↑  Inline assembly *clang.llvm.org*. Viitattu 12.9.2020. (englanniksi)

Aiheesta muualla
----------------

* Kuvia tai muita tiedostoja aiheesta **Assembly (ohjelmointikieli)** Wikimedia Commonsissa

### Kirjallisuutta

* Jorgensen, Ed: *x86-64 Assembly Language Programming with Ubuntu*. , 2020. Teoksen verkkoversio (PDF). (englanniksi)
* Dennis Yurichev: *Understanding Assembly Language* (PDF) (englanniksi)
* Randall Hyde: *The Art of Assembly Language* - eri versioita saatavilla (englanniksi)

#### Suomeksi

* Link, Wolfgang: *Assembler-ohjelmointi*. Suomentanut Reijo Lundahl. Vantaa: Pagina, 1997. ISBN 951-644-108-4. Finna.fi-tietokanta.
* Maljugin, Vitaly; Izrailevich, Jacov; Lavin, Semyon; Sopin, Aleksandr: *Inside assembler: ohjelmoijan käsikirja*. Toimituksellinen neuvonantaja: Ivor Horton. Suomennetun laitoksen oikolukenut T. Eklin. Helsinki: IT Press, 1999. ISBN 951-826-006-0. Finna.fi-tietokanta.

|  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * n
* k
* m
Yleisimmät ohjelmointikielet |
| --- |
|  |
| Tuotantokäytössä | 
* Ada
* APL
* Assembly
* AWK
* C
* C++
* C#
* COBOL
* Dart
* Delphi
* Eiffel
* Erlang
* Forth
* Fortran
* Go
* Java
* JavaScript
* Kotlin
* Lisp
* Lua
* Objective-C
* Pascal
* Perl
* PHP
* PostScript
* Python
* R
* Ruby
* Rust
* Smalltalk
* Swift
* Tcl
* TypeScript
* Visual Basic

 |
|  |
| Akateemiset | 
* CLU
* Haskell
* Logo
* ML
* OCaml
* Prolog
* Scheme

 |
|  |
| Historialliset | 
* ALGOL
* BASIC
* Modula-3
* MUMPS
* Plankalkül
* PL/I
* Simula

 |
|  |
| Luettelo yleisimmistä ohjelmointikielistä |

 |

|  |  |  |
| --- | --- | --- |
| 

|  |  |
| --- | --- |
| Auktoriteettitunnisteet: Kansalliset Muokkaa Wikidatassa | 
* Ranska
* BnF data
* Saksa
* Israel
* Yhdysvallat
* Tšekki

 |

 |