5. diel - Assembler - Dátové typy a premenné
V minulej lekcii, Assembler - ASCII tabuľka a spustenie v DOSBox , sme si vysvetlili ASCII tabuľku, dokončili opis Hello world! programu a spustili si ho ako .Com súbor v emulátora DosBox.
V dnešnej lekcii sa budeme podrobnejšie venovať dátovým typom v ASM a samozrejme premenným.
Typový systém
Dátové typy v ASM nie sú rozdelené klasicky podľa toho, pre aký typ
obsahu sú určené. Každý z nás pozná určite Int
,
String
alebo Boolean
z vyšších programovacích
jazykov, ktoré potom vo finále zaberali v pamäti určitý počet bajtov.
Prekladač tiež kontroloval, či jednotlivé dátové typy všade sedí. V ASM
definujeme rovno koľko pamäte sa má pre určitú premennú vyhradiť a už
nikto nekontroluje, čo do tohto priestoru potom ukladáme.
Definície premenných v ASM
V minulých lekcií sme si už premennú vytvárali a tiež určili jej
dátový typ. Bolo to pri programe Hello world, kde premenná
hlwrld
typu DB
obsahovala text
"Hello world!"
, Končiace ešte znaky pre koniec riadku a
reťazca:
hlwrld db "Hello, World!", 10, 13, 0
Premenné v ASM teda deklarujeme štýlom: název typ hodnota
. Z
toho vyplýva, že DB
je nejaký dátový typ premennej. Poďme si
tieto direktívy predstaviť bližšie.
Direktívy DB
, DW
a
DD
V Assemblera nájdeme týchto päť typov premenných, ale v skutočnosti je to taký menší podvod. Jediný rozdiel je totiž ich veľkosť. V tejto tabuľke sú direktívy a ich veľkosti:
direktíva | celý názov | veľkosť | rozsah |
---|---|---|---|
DB | Define Byte | 1 bajt | -128 až 255 |
DW | Define Word | 2 bajty | -32768 až 65535 |
DD | Define Doubleword | 4 bajty | -2147483648 až 4294967295 |
DQ | Define Quadword | 8 bajtov | Príliš veľké čísla |
DT | Define Ten Bytes | 10 bajtov | Príliš veľké čísla |
U direktív define (to sú všetky v tabuľke uvedené) musíme premennú zároveň tiež inicializovať. Pre prácu s neinicializovanými premennými sa používajú potom zas iné direktívy.
Uloženie čísla do premennej
Číslo do premennej v Assemblera uložíme veľmi jednoducho, iba určíme veľkosť v bajtoch pomocou príslušnej direktívy:
male_cislo DW 15 cislo DW 23093 negativni_cislo DW -23093 vetsi_cislo DD 342183449 desetinne_cislo DD 1.552 desetinne_cislo2 DQ 123.456
Negatívne čísla sa ukladajú ako dvojkovej doplnky. Pre viacbajtové hodnoty procesor používa malú endianita. Ak vám tieto pojmy nič nehovoria, sú vysvetlené v kurze Princípy fungovania počítačov.
Uloženie reťazca do premennej
Ako je ale možné, že do premennej veľkosti 1 bajt môžeme uložiť
ľubovoľne dlhý textový reťazec? Pri použití reťazca v úvodzovkách
alebo apostrofmi ''
v direktíve DB
sa pre každé
písmeno samozrejme vyhradí jeden bajt. Tento kód:
hlwrld db "Hello, World!", 10, 13, 0
Je vlastne len skrátený zápis:
hlwrld db "H", "e", "l", "l", "o", ",", " ", "W", "o", "r", "l", "d", "!", 10, 13, 0
Čo je skrátený zápis z:
hlwrld db "H" db "e" db "l" db "l" db "o" db "," db " " db "W" db "o" db "r" db "l" db "d" db "!" db 10 db 13 db 0
Doplnenie reťazca na násobky bajtov
Možno vás napadlo, čo by sa stalo, keby sme premennú s reťazcom
definovali namiesto DB
napr. Pomocou DW
alebo
ďalšími direktívami pre väčšie dátové typy. Fungovalo by to, ale
výsledok by vždy zaberal násobok počtu bajtov daného dátového typu (napr.
V prípade DW
násobok 2) a text by bol na konci doplnený
nulovými znaky, aby mal požadovanú dĺžku. Napr. text "ABCDEF"
by bol pri deklarácii ako:
text dd 'ABCDE'
uložený ako:
0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x00 | 0x00 | 0x00 |
Ale čo tá divná čísla? Hodnoty bajtov v pamäti väčšinou vypisujeme
ako hexadecimálne čísla, pretože je tento zápis kratšia. Okrem písmená
H
sa čísla v šestnástkovej sústave označujú niekedy aj ako
0x
. Už vieme, že ASCII kód znaku A
je
65
a vidíme, že prvý bajt má hodnotu 0x41
, kde
41
hex je naozaj 65
dec a teda znak
A
.
Ako reťazec môžeme uložiť napr. Aj znak "y"
/
"n"
pre reprezentáciu voľby užívateľa:
znovu DB 'y'
Premenné a registre
Teraz už vieme, ako premenné deklarovať a aké sú veľkosti jednotlivých typov. Teraz si ukážeme, ako sa dajú premenné kombinovať s registrami a medzi sebou.
Rovnako ako u registra je dôležité dodržiavať veľkosť. Tu sú príklady pre kombináciu s registrami pre prekladač NASM.
S 8-bitovým registrom:
; s 8bitovým registrem mov byte [value], al ; Do proměnné value přesuneme hodnotu z registru AL. mov al, byte [value] ; Do registru AL přesuneme hodnotu z proměnné value. value db 0 ; Definujeme proměnnou value.
S 16-bitovým registrom:
; s 16bitovým registrem mov word [value], ax ; Do proměnné value přesuneme hodnotu z registru AX. mov ax, word [value] ; Do registru AX přesuneme hodnotu z proměnné value. value dw 0 ; Definujeme proměnnou value
Priradenie z premennej do premennej
Ak chceme preniesť hodnotu z jednej premennej do druhej, musíme použiť register:
; přenesení hodnoty z jedné proměnné do druhé mov al, byte [value1] ; Do registru AL přesuneme hodnotu z proměnné value1 mov byte [value2], al ; Do proměnné value2 přesuneme hodnotu z registru AL value1 db 0 ; Proměnná value1 value2 db 0 ; Proměnná value2
Takto by sme pracovali s číselnými hodnotami, ale ako sa to robí s textom?
Polohovacie registre
Ak chceme pracovať s textom, je dobré naučiť sa pracovať s polohovacím
registre. Tie spadajú pod univerzálne registre a patria sem registre
DI
a SI
. Pre "čítanie" textu sa používa
SI
a pre nejaké úpravy DI
. Oba dva registre sú
16-bitové. Už sme sa s nimi stretli v lekcii o
programe Hello world.
Register SI
(Source Index)
Register SI
je ukazovateľ na zdrojové dáta pri kopírovacích
operáciách.
Register DI
(Destination
Index)
Register DI
je ukazovateľ na cieľová dáta pri kopírovacích
operáciách.
Tu je kód k programu nazvanému Písmenká. Program "analyzuje" vetu v
premennej veta
a vyberie z nej písmenká "a"
, ktorá
presunie do premennej pismenka
. Pracuje sa tu ako s registrom
DI
, tak s registrom SI
. Kód je napísaný pre
emulátor EMU8086, ktorý nájdete v prílohe spolu s kódom:
org 100h main: mov di, [pismenka] ; Nastavíme registr DI na proměnnou pismenka mov si, [veta] ; Nastavíme registr SI na proměnnou veta get_char: lodsb ; Načteme znak z proměnné veta do registru AL cmp al, 'a' ; Pokud je znak 'a'... jz add_char ; ...skoč na add_char cmp al, 0 ; Pokud je číslo znaku 0 (null)... jz continue ; ...skoč na continue jmp get_char add_char: mov byte [di], al ; Přesuneme znak do registru DI (do proměnné pismenka, namísto registru AL můžeme napsat i 'a') a... inc di ; ...posuneme se na další místo v proměnné jmp get_char continue: mov byte [di], 0 ; Do registru DI (do proměnné pismenka) přesuneme číslo 0 (null) mov si, [pismenka] ; Nastavíme registr SI na proměnnou pismenka print: lodsb ; Načteme znak z proměnné pismenka do registru AL cmp al, 0 ; Pokud je číslo znaku 0 (null)... jz return ; ...skoč na return mov ah, 0eh ; Funkce BIOSu pro teletypový výstup mov bx, 7h int 10h ; Vypiš znak jmp print return: ret ; Vrať kontrolu operačnímu systému veta: db "Ahoj, jak se mas, Karle?", 0 ; Proměnná veta pismenka: db 0 ; Proměnná pismenka
Môžete si všimnúť, ako sa s takými polohovacím registrami pracuje. Tu je jednoduchšie príklad:
mov di, [text] mov byte [di], 97 inc di mov byte [di], 98 inc di mov byte [di], 99 inc di mov byte [di], 0 mov si, text print_string: lodsb or al, al jz short end mov ah, 0eh mov bx, 7h int 10h jmp print_string end: ret text: db 0
Presunutím premenné text
do registra DI
povieme
registra, na čo má ukazovať. Nasledovne nastavíme prvý znak na
"a"
, inštrukcií INC
posunieme ukazovateľ na
ďalší znak, kam zapíšeme "b"
a tak ďalej ...
Inštrukcia INC
(Increment)
Inštrukcie INC
má jeden parameter a tým môže byť register
alebo premenná. Z anglického increment vyplýva, že inštrukcie má za úlohu
"pripísať číslo jedna" buď do registra, alebo do premennej.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 613x (2.68 MB)