ASSEMBLER - jazyk symbolických adres
Program je tvořen dvěma druhy klíčových slov:
Direktivy nevytvářejí kód programu, ale řídí činnost překladače.
Instrukce jsou symbolickým zápisem strojových instrukcí procesoru.
Syntaxe zápisu instrukce:
návěští instrukce cíl, zdroj ; komentář
Návěští je symbolické jméno, které označuje offset v daném segmentu.
Návěští:
blízká (NEAR)
vzdálená (FAR)
Blízká návěští představují pouze offsetovou část adresy. Používají se v případě, že se na návěští odkazujeme v rámci segmentu, ve kterém je definováno. Identifikátor blízkého návěští se od instrukce odděluje dvojtečkou.
Vzdálená návěští představují kompletní adresu. Pro definici vzdáleného návěští se používá direktiva LABEL.
Cíl a zdroj jsou operandy instrukce. Operandem může být registr, konstanta, paměťové místo.
Komentář je libovolný text, oddělený od instrukce středníkem.
Direktivy nemají přesnou syntaxi zápisu. Pro označení proměnných, návěští, konstant se používají symbolická jména - identifikátory. V assembleru je identifikátor libovolné slovo složené ze znaků: $, % , - , ?, A...Z, a...z, 0-9. Identifikátor nesmí začínat číslicí a nelze pro ně použít rezervovaná slova. Malá a velká písmena se v assembleru nerozeznávají.
Paměť je rozdělena na segmenty o velikosti 64 kB. Každý segment je určen segmentovou adresou, která je uložena v některém ze segmentových registrů. Velikost adresy je 16 bitů. Posunutí v segmentu je relativní adresa, vzhledem k jeho počátku, určuje offset. Instrukce programu leží vždy v segmentu označeném registrem CS. Direktiva MODEL umožnuje automatické definování segmentů a jejich vlastností.
Syntaxe:
MODEL paměťový model
Paměťový model blíže určuje jedno ze slov, slovo určuje velikost programu.:
např. MODEL TINY
Všechny segmenty začínají na stejné adrese a velikost programu nesmí překročit 64 kB, tj. jeden segment. Tento model je nutno používat pro programy typu .com.
Šablona pro psaní programu typu .com:
IDEAL; zvolení režimu překladače
MODEL tiny; určení velikosti programu
DATASEG; označení datového segmentu
CODESEG;
STARTUPCODE;
<zde bude umístěn kód programu>
EXITCODE; ukončení programu
END
DATA
Pro definici dat je syntaxe:
[jméno] direktiva [výraz [, výraz...]]
Jméno je identifikátor, který označuje paměťové místo, je to ukazatel na místo v daném segmentu. Obsahuje adresu a instrukce o velikosti dat. Velikost určuje direktiva:
Direktiva | Velikost |
DB | 1 byte |
DW | 2 byte (slovo) |
DD | dvojslovo (32 bitů) |
DQ | čtyřslovo (64 bitu) |
DF | 6 bytů (80386 ukazatel FAR) |
DP | 6 bytů (80386 ukazatel FAR) |
DT | 10 bytů (pro reálná čísla) |
Výraz: definuje obsah paměťového místa. V případě, že nechceme inicializovat, uvedeme ?. Když ano, uvedeme libovolnou číselnou hodnotu nebo výraz, který se vyhodnotí na číselnou hodnotu. U direktivy DW lze inicializaci provést pomocí řetězce znaků, uzavřeného v úvozovkách nebo apostrofech. Jednotlivé znaky se nahradí ascii hodnotami, kde se pro každý znak vytvoří místo o velikosti 1 B. Výrazy se vyhodnocují při překladu zdrojového textu. Základem výrazu jsou konstanty. Číselné konstanty se mohou zapisovat ve dvojkové, osmičkové, desítkové a šestnástkové soustavě. Číslo musí vždy začínat číslicí. Implicitní soustava je určena direktivou RADIX. Číslo v jiné než implicitní soustavě se napíše tak, že se za něj napíše základ (znak).
RADIX
Syntaxe:
RADIX základ
Základ - 2, 8, 10, 16.
Soustava | Znak |
Dvojková | B |
Osmieková | O,Q |
Desítková | D |
Šestnáctková | H |
Postup při vytváření programu typu .com:
Větvení programu:
Ve vyšších programovacích jazycích se provádí příkazy IF, GOTO, atd. U asembleru se větvení provádí pomocí instrukcí skoku.
Instrukce skoku: podmíněné, nepodmíněné.
Nepodmíněný skok
Syntaxe:
JMP [vzdálenost] cíl
Cíl je návěští, na které chceme skočit, pokud skáčeme uvnitř segmentu, je vzdálenost NEAR, jinak FAR.
Např.
JMP NEAR Reet
. .
. .
Reet: MOV DX, OFFSET BUFFER
Podmíněný skok
Syntaxe:
J podmínka návěští
Provádí se na základě nastavení jednotlivých bitů v registru příznaků. Návěští u podmíněného skoku musí být ve vzdálenosti -128 až +127 bytů od instrukce skoku. Podmínka určuje, kdy se skok provede. Před provedením instrukce podmíněného skoku je nutno nastavovat bity v příznakovém registru. Provádí se instrukcí CMP.
Např.
CMP BL,2
JA ERROR
. .
. .
ERROR:MOV DX,OFFSET MESSAGE
MOV AH,09H
INT21H
CMP
Syntaxe:
CMP cíl, zdroj
Instrukce odečte zdroj od cíle a podle toho nastaví bity v příznakovém registru, obsah cíle ani zdroje se nemění.
Cykly
V assembleru se realizují pomocí instrukcí skoku. Pomocí JNZ je realizován cyklus DO - WHILE.
Příklad:
CODESEG
. .
návěští:
<tělo cyklu>
JNZ návěští
Cyklus FOR (for i =1 to 10):
MOV CX,1
LOOP1,<tělo cyklu>
INC CX
CMP CX,10
JNZ LOOP1
Jeden z registrů se použije jako čítač, který při každém průchodu dekrementuje nebo inkrementuje a před podmíněným skokem porovnáváme s nějakou hodnotou.
Instrukční soubor 80386
NOP
Syntaxe:
NOP
Prázdná instrukce, neprovádí nic, změní jen obsah čítače programu.
INC
Syntaxe:
INC reg
Instrukce přičte ke svému operandu jedničku a výsledek do něj opět uloží.
DEC
Syntaxe:
DEC reg
Instrukce odečte od svého operandu jedničku a výsledek do něj opět uloží.
DIV
Syntaxe:
DIV oper
Instrukce dělí celá čísla bez znaménka, má jen jeden operand, výsledkem dělení je dvojice čísel: celočíselný podíl, celočíselný zbytek.
Velikost operandu | Dělenec | Dělitel | Podíl | Zbytek |
8 bitů | AX | operand | AL | AH |
16 bitů | DX:AX | operand | AX | DX |
32 bitů | EDX:EAX | operand | EAX | EDX |
Např. při bytovém dělení je dělenec v registru AX, podíl v AL a zbytek v AH. Znamená to, že umístění dělence, podílů a zbytků závisí na velikosti operandů.
Zásobník
LIFO (Last In First Out)
Ukládají se přechodně: obsahy registrů, návratové adresy.
Údaj naposled vložený do zásobníku zaujímá vždy nejnižší adresu. Zásobník je vymezená souvislá část paměti RAM. Nejnižší adresa je vrchol zásobníku. Adresa vrcholu zásobníku je obsažena v ukazateli SP. Údaje jsou do zásobníku vkládány v pořadí. Na vrcholu je vždy údaj, který byl vložen jako poslední. Zásobník se plní směrem k nižším adresám a vyprazdňuje směrem k vyšším adresám. Zvyšování nebo snižování obsahu provádí mikroprocesor při instrukcích, pracujících se zásobníkem.
Vyjmutí ze zásobníku:
POP
Syntaxe:
POP oper
Instrukce vyjme slovo nebo dvojslovo ze zásobníku a uloží ho do operandu. Pak se k obsahu registru SP přičtou 2, pokud je vybíráno slovo nebo 4, pokud je vybíráno dvojslovo. Při vybírání ze zásobníku se adresa SP zvyšuje.
Příklad: POP AX
POP A
Instrukce vybírá 8 základních registrů ze zásobníku:
DI, SI, BP, SP, BX, DX, CX, AX. Lze ji nahradit osmi instrukcemi POP.
Ukládání na zásobník:
PUSH
Syntaxe:
PUSH oper
Instrukce uloží obsah registru, paměti nebo přímo hodnotu na zásobník. Ukazatel vrcholu zásobníku ukazuje na naposledy uloženou položku. Nejprve se odečtou od obsahu registru SP 2 (ukládáme-li slovo) nebo 4 (ukládáme-li dvojslovo), takže registr SP ukazuje na volné místo. Pak se zapíše obsah registru, paměti nebo konstanty. Při ukládání do zásobníku se adresa registru SP snižuje.
PUSH A
Instrukce ukládá 8 základních registrů do zásobníku:
AX, CX, DX, BX, SP, BP, SI, DI. Po provedení této instrukce je obsah registru AX na nejvyšší adrese v zásobníku a DI je na nejnižší adrese v zásobníku.
ADD
Syntaxe:
ADD oper1, oper2
Instrukce provádí součet dvou operandů. oper1 = oper1 + oper2
Např:
MOV AX,2
MOV BX,3
ADD AX,BX ; AX [5]
MOV
Syntaxe:
MOV oper1, oper2
Instrukce naplní operand oper1 operandem oper2, přitom oper2 zůstane beze změny.
Např:
MOV BX,4
MOV BX,AX
MUL
Syntaxe:
MUL oper1
Instrukce provádí násobení celých čísel bez znaménka.
Velikost | 1. činitel | 2. činitel | Součin |
8,00 | AL | operand | AX |
16,00 | AX | operand | DX:AX |
32,00 | EAX | operand | EDX:EAX |
1. oper1 je 1B
Oper1 se vynásobí registrem AL a výsledek se uloží do AX. Když je výsledek větší než 1B, nastaví se příznaky OF a CF, jinak se oba příznaky nulují.
2. oper1 je slovo
Oper1 se vynásobí registrem AX a výsledek se uloží do DX a AX tak, že nižší část výsledku je v registru AX a vyšší v DX. Je-li výsledek větší, nastaví se OF a CF.
3. oper1 je dvojslovo
Oper1 se vynásobí registrem EAX a výsledek se uloží do EDX a EAX tak, že nižší část výsledku je v registru EAX a vyšší v EDX.
SUB
Syntaxe:
SUB oper1, oper2
Instrukce provádí odčítání celých čísel. oper1 = oper1 - oper2
Logické instrukce
AND
Syntaxe:
AND oper1, oper2
Instrukce provádí logický součin operandů podle vzorce. oper1 = oper1 AND oper2
Instrukce AND | ||
1. bit | 2. bit | Výsledný bit |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
NOT
Syntaxe:
NOT oper1
Instrukce provádí negaci všech bitů operandu oper1 tak, že bit s hodnotou 1 bude nulový a naopak.
Příklad: NOT BX
OR
Syntaxe:
OR oper1, oper2
Instrukce provádí logický součet operandů podle vzorce. oper1 = oper1 OR oper2
Instrukce OR | ||
1. bit | 2. bit | Výsledný bit |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
XOR
Syntaxe:
XOR oper1, oper2
Instrukce provádí neekvivalenci operandů podle vzorce. oper1 = oper1 XOR oper2
Instrukce XOR | ||
1. bit | 2. bit | Výsledný bit |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Procedury
Procedura je libovolná část kódu programu, která je ukončena instrukcí RET. Návěští označuje začátek procedury.
CALL
Syntaxe:
CALL oper1
Instrukce provede vstup do podprogramu tak, že nejprve se na zásobník uloží návratová adresa a pak se provede skok do podprogramu. Návratová adresa: segment - vyšší část adresy, offset - nižší část adresy. V závislosti na tom, zda podprogram ve stejném segmentu jako hlavní program je i: NEAR - na zásobník se uloží jen offsetová část adresy.
Podle typu volání je i instrukce RET: RETN, RETF.
Instrukce RET způsobí návrat z procedury.
RET
Syntaxe:
RET oper1
Oper1 udává, kolik bytů se odstraní ze zásobníku po vyjmutí návratové adresy.
CODESEG
..................
CALL NEAR PROC1
....................
PROC1:
;zde bude kód procedury
RETN
Schéma procedury v ASM
Volání direktivou PROC
Schéma volání
. .
. .
CODESEG
. .
. .
CALL PROC2
. .
PROC PROC2
;zde budou instrukce procedury
RET
Při použití direktivy MODEL nemusíme specifikovat, zda je procedura blízká nebo vzdálená. Překladač vybere správný typ podle zadaného modelu. Předávání parametrů pomocí zásobníku:
na zásobník se umístí předávané parametry instrukcí PUSH.
Např:
MOV AX,PARAM1
PUSH AX
MOV AX PARAM2
PUSH AX
CALL PROC2
Adresa | Obsah |
SP | Návratová adresa |
SP + 2 | Parametr 2 |
SP + 4 | Parametr 1 |
Po návratu z procedury je nutno hodnoty ze zásobníku vyjmout. Provádíme instrukci POP.
Souvisejici odkazy
http://nwinfo1.vsb.cz/~.l96892.stii.fei/vyuka/assamble/ucebnice.htm