Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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
Nenechajte sa zmiasť slovom "Word", nejedná sa o nič v spojitosti so slovom alebo textom, ale iba o termín určujúce veľkosť 2 bajty.

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
(Teda ako 8 bajtov, čo sú 2 doubleword)

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 podmienkami

Stiahnuté 572x (2.68 MB)

 

Predchádzajúci článok
Assembler - ASCII tabuľka a spustenie v DOSBox
Všetky články v sekcii
Assembler
Článok pre vás napísal Jakub Verner
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje programování v x86 Assembleru.
Aktivity