Masinkood ja assembler

Arvuti on (äärmiselt abstraheeritult) kast, mis on jagatud ruudukesteks (mälupesadeks ). Iga ruuduke võib :

- sisaldada musta palli (bit "0");
- sisaldada valge palli (bit "1");
- olla tühi.

Arvutamine (programmi käivitamine/täitmine) koosneb sammudest/instruktsioonidest, kus igal sammul:

- kirjutatakse midagi ("0" või "1") mingisse ruudukesse (mälupesasse) - kuid konkreetset mälupesa saab näidata vaid siis, kui on kokku lepitud mingi viis ruudukeste/mälupesade adresseerimiseks ; järgnevas oletame (lihtsustatult), et mälupesad on aderesseeritud järjestikuste arvudega (näiteks) kaheksandsüsteemis ( reaalseted arvutid võivad kasutada näiteks heksadetsimaalsüsteemi (hex) );
- loetakse midagi ("0" või "1") mingist ruudukest (mälupesast). Kuid loetu on tarvis kuidagi salvestada, sellepärast on arvutis mingi (lõplik, väike) arv registreid - mälupesad, mis on vahetulemuste ja operatsioonide argumentide salvestamiseks ( kuna need peavad olema väga kiired, siis tavaliselt väga väike arv);
- tehakse mingi (aritmeetiline, loogiline) operatsioon (binaarne - kahe argumendiga, unaarne - ühe argumendiga; kuna operatsioon salvestatakse samades mälupesades, peab olema fikseeritud mingi mälupesade hulk, kus fikseeritud 0/1-de jada kirjeldab operatsiooni, s.t. operatsioonidel on kahendkood); siin on mitmeid võimalusi sõltuvalt argumentide ja tulemuse adresseerimise võimalustest:
- operandid (mõlemad mälupesadest), tulemus - mälupesasse (kolmeaadressiline süsteem - keerukas ja kallis);
- operandid (mõlemad) mälupesadest, tulemus - fikseeritud registrisse või
- üks operand - mälupesast, teine ja tulemus - fikseeritud registritest (üheaadressiline süsteem).

Operatsiooni sooritamine, selle tulemuse salvestamine ja järgmisena täidetava instruktsiooni valik võib sõltuda mingitest väärtustest (mis on salvestatud mälupesades või registrites), seega on tarvis ka tingimuslauset :
if (mälupesa/registri väärtus) then (operatsioon).

Kuid sõltumata sellest, milline on operatsioonide kirjeldamise süntaks, on arvuti alati lõplik automaat , mille olekute arv on 2**(mälupesade+registrite arv) - arvuti olek (igal hetkel) on määratud tema mälupesade ja registrite sisuga.

Selle lõpliku automaadi tööd juhib protsesso, mis operatsiooni (automaadi oleku muutuse) kirjelduse põhjal muudab automaadi olekut. Kirjeldus esitatakse protsessorile bitijadana, kus on operandide aadressid, operatsiooni kood ja tulemuse aadress, s.t. käsk võiks välja näha nii
001010100011 ja selle bitijada tähendus (semantika) võiks olla:

võta arvud pesadest 001 ja 010, liida need (kood 100) ja salvesta tulemus pesas 011 - see oleks binaarne masinkood kolmeaadressilises süsteemis.

Esimeste arvutite jaoks pidid selliseid bitijadasid konstrueerime programmeerijad. Selline programmeerimisviis (bitijadadena masinkoodis) on äärmiselt inimvaenulik - inimesed teevad selliste bitijadade käsitlemisel väga palju vigu.

Esimese sammuna koodi "inimlikustamisel" oli nn sümboolsete nimede kasutuselevõtt, näit koodi "100" asemel kirjutati "add" - sündis assemblerkeel. Assemblerkeel on vaid masinkoodi bitijadade (mehhaaniline) asendus operatsioonide ja muutujate nimedega, kuid inimesele juba palju lihtsamini arusaadavam ja lihtsam. Järk-järgult lisandusid programmeerimiskeeltesse üha keerukamad konstruktsioonid: ühe tehte asemel (masinkoodis ja ka assembleris sooritab iga käsk vaid ühe aritmeetilise või loogilise operatsiooni) sai kirjutada juba terve mitmesuguseid matemaatilisi funktsioone sisaldava avaldise, toodi sisse juhtimiskonstruktsioonid (if-then(-else), tsüklid), moodulid, objektid jne jne). Kuid programmi täitmisel peab kõik need kaasaegsete programmeerimiskeelte konstruktsioonid algul programmi tekstist üles leidma ja teisendada masinkoodi - see on ainuke, millest protsessor "aru saab".

Translaatori ülesanne ongi algul "avastada" transleeritava programmi struktuur (süntaks), leida selles käsud, muutujate deklaratsioonid, alamprogrammid/moodulid/klassid ja siis (näiteks) teisendada kõrgtaseme keele käsk

IF A OR (B AND C) THEN X := Y + Z

ja siis teisendada see assemblerkoodiks (või mõneks teiseks programmeerimiskeeleks), näiteks selliseks:

100 IF A GOTO 106
101 GOTO 102
102 IF B GOTO 104
103 GOTO 108
104 IF C GOTO 106
105 GOTO 108
106 T1 := Y+Z
107 X := T1

Kogu probleem on stringi (sisendteksti; nii lähtetekst kui ka tulemus on märgijadad, s.t. stringid!) struktuuri avastamine ja selle stringi teisendamine. Osutub, et nii struktuuri avastamist kui ka väljundi genereerimist on võimalik etappide kaupa nii kirjeldada, et kogu teisenduse programm (s.t. translaator) genereeritakse sellest kirjeldusest (pool)automaatselt.

Kuid sellisest formaalsest translaatorite genereerimise süsteemi kirjeldamiseks ja sellest arusaamiseks on tarvis aru saada ja osata kasutada sümbolijadade hulkade (keelte) teisendamise formalismidest - abstraktsetest automaatidest ja grammatikatest.


Ülesandeid:
1. Ylesande tekst

Küsimused, probleemid: ©2004 Jaak Henno