Az Assembly programozási nyelv

Utasítások, vezérlési szerkezetek

Utasítások

Értékadás

Az assembly nyelvben az értékadást a mov parancs jelenti. Értékadás bal oldalán állhat regiszter, vagy memóriaterület. A jobb oldalon állhat regiszter, memóriaterület, vagy konstans érték. Tehát nincs lehetőség függvényeket, vagy kifejezéseket helyezni a jobb oldalra. Van viszont típusellenőrzés fordítási időben. Arra nyilván nincs lehetőség, hogy különböző méretű regisztereket egymásnak értékül adjunk, de az assembler akkor is hibaüzenetet ad, ha például egy BYTE méretű regisztert akarunk értékül adni egy WORD típusú memóriaterületnek. Az alábbi kód tehát hibás:
label1: WORD 1 ... mov label1,AL

Más a helyzet, ha a memóriaterület pointere egy regiszterben található. A pointereknek ugyanis nincs típusuk, tehát az assembler nem tudja, hogy futási időben a regiszter milyen típusú adat pointerét fogja tartalmazni. Az alábbi kód tehát helyes:
label1: WORD 1 ... mov EDI,offset label1 mov [EDI],AL

Ebben az esetben a második mov parancs csak a label1 által jelölt WORD típusú adat alsó 8 bitjét fogja felülírni AL tartalmával (mivel a WORD típusú adatnak az alsó 8 bitje áll elől a memóriában). Ez felfogható hibának, de felfogható lehetőségnek is, hiszen így szabadabban változtathatjuk az adatainkat. Ennek persze megvan az ára, jobban oda kell figyelni, hogy minek mit adunk értékül, mert az assembler nem mindig látja a hibát.

Vezérlési szerkezetek

Ciklusok

Az assembly nyelv egyetlen iterációt ismer, a ciklusszámlálós ciklust. A ciklusszámláló mindig a CX illetve ECX regiszterben található attól függően, hogy megengedettek-e 32 bites utasítások. Ebben az esetben a ciklusszámláló regiszter tartalma előjel nélküli egész számként értendő.
mov CX,100h label1: ;ciklusmag ... loop label1

A fenti példában a ciklusmag 256-szor fut le, ami alatt CX regiszter értéke 0-ra csökken.
mov CX,100h label1: push CX mov CX,100h label2: ;ciklusmag ... loop label2 pop CX loop label1

A fenti példában két egymásba ágyazott ciklust láthatunk, a ciklusmag összesen 65536-szor fut le. Mivel mindkét ciklus számlálója a CX regiszter, ezért nagyon fontos, hogy mielőtt a belső ciklus elindul, CX regiszter tartalmát elmentsük (a példában a verembe kerül), és a belső ciklus lefutása után visszaállítsuk ezt az elmentett értéket.

Bizonyos speciális célokra létezik egy másik módja is az iterációnak is. A szakirodalom ezeket string kezelő utasításoknak hívja. A rep, repz és repnz prefixszel ellátott utasítások addig futnak, amíg egy bizonyos feltétel fennáll, így végül is tekinthetők while ciklusnak. A rep prefix utáni utasítás addig ismétlődik, amíg a ciklusszámláló értéke pozitív. A repz utáni utasítás addig ismétlődik, amíg a ciklusszámláló értéke pozitív, és a zero flag értéke 0. A repnz utáni utasítás addig ismétlődik, amíg a ciklusszámláló értéke pozitív, és a zero flag értéke 1.
A fenti prefixek a következő utasításokkal használhatók (Az alábbi utasítások utolsó karaktere a byte rövidítése. Használható helyette w - word illetve d - dword. Ilyenkor AL helyett AX illetve EAX regiszter értendő, és DI,SI regiszterek egy helyett kettővel illetve néggyel növekednek):

movsb jelentése:
ES:[DI] := DS:[SI] inc DI inc SI
cmpsb jelentése:
cmp DS:[SI],ES:[DI] inc DI inc SI
lodsb jelentése:
mov AL,DS:[SI] inc SI
stosb jelentése:
mov ES:[DI] inc DI
scasb jelentése:
cmp AL,ES:[DI] inc DI

Elágazások

Csak feltételhez kötött ugró utasításokkal lehet elágazást megoldani, ezekről a következő pontban lesz szó.

Ugró utasítások

Feltétel nélküli ugró utasítás a jmp, ami után meg kell adni egy cimkét. A jmp után a cimke utáni első utasítástól folytatódik a program futása. Bár néhány magas szintű programnyelv teljesen nélkülözi az ugró utasításokat, az assembly nyelvben fontos szerepük van, hiszen while ciklusokat, és elágazásokat csak ugró utasításokkal lehet megoldani, mivel egyébként nem szerepelnek a nyelvben.

A feltételes ugró utasítások abban különböznek a fentiektől, hogy az ugrás feltételhez van kötve. Ha a feltétel nem teljesül, akkor a program futása az ugró utasítást követő utasítástól folytatódik. Sok ilyen feltétel létezik, ennek megfelelően sokféle ugró utasítás. Itt most csak néhány példa következik.
jz label - a zero flag értéke 1, tehát az utolsó művelet eredménye 0 volt.
jnz label - a zero flag értéke 0
jc label - a carry flag értéke 1
jnc label - a carry flag értéke 0
ja label - az előző előjel nélküli kivonás eredménye pozitív lett
jg label - az előző előjeles kivonás eredménye pozitív lett

Példa elöl tesztelős while ciklus megvalósítására ugró utasításokkal
label1: ;feltétel kiértékelése, a feltétel értéke a carry flag-be kerül ... jnc label2 ;a ciklusmag ... jmp label1 label2:
Ha a fenti módon járunk el, akkor egyszerűen megvalósítható a ciklust elhagyó break, és a ciklus elejére ugró continue utasítás is:
;break megvalósítása a fenti példában jmp label2 ;continue megvalósítása jmp label1
Példa if-then-else elágazás megvalósítására ugró utasításokkal
;feltétel kiértékelése, a feltétel értéke a carry flag-be kerül jnc label1 ;then ág ... jmp label2 ;else ág ... label2: