MEMÓRIAVÁLTOZÓK HASZNÁLATA
A következő lépésben egy általunk meghatározott xy koordinátára fog kiírni egy
letárolt karaktert. Ennek lényege, hogy az eltolási értéket a program fogja kiszámolni a
megadott értékek alapján:
| Pelda03 | Segment | ;Szegmensdefinicio. |
| assume cs:Pelda03,ds:Pelda03 | ;Cs es ds regiszterek bealli- | |
| ;tasa a szegmens elejere. | ||
| Start: | mov ax,Pelda03 | ;A ds regiszter beallitasa. |
| mov ds,ax | ||
| mov ax,0b800h | ;A kepernyomemoria szegmens- | |
| mov es,ax | ;cimet es regiszterbe tolti. | |
| mov al,byte ptr [KOORD_Y] | ;Al regiszterbe tolti a | |
| ;KOORD_Y cimke alatt tarolt | ||
| ;erteket. | ||
| mov bl,160 | ;Bl-be 160-at tolt, mivel | |
| ;egy sor 160 byte. | ||
| mul bl | ;Al erteket megszorozza bl | |
| ;erekevel. | ||
| mov di,ax | ;Az igy kapott eredmenyt | |
| ;di indexregiszterbe tolti. | ||
| mov al,byte ptr [KOORD_X] | ;A vizszintes pozicio erteket | |
| ;al regiszterbe tolti | ||
| mov bl,2 | ;es megszorozza 2-vel | |
| mul bl | ||
| add di,ax | ;majd hozzaadja di-hez. | |
| mov al,byte ptr [BETU] | ;Al-be a betu kodjat ah-ba | |
| mov ah,byte ptr [SZIN] | ;pedig a szinkodot tolti. | |
| mov es:[di],ax | ;Az es:di alltal mutatott | |
| ;cimre irja ax tartalmat azaz | ||
| ;a fekete alapon feher "A" | ||
| ;betut. | ||
| mov ax,4c00h | ;Kilepes a DOS-ba. | |
| int 21h | ||
| KOORD_X: | db 40 | |
| KOORD_Y: | db 12 | |
| BETU: | db "A" | |
| SZIN: | db 7 | |
| Pelda03 | Ends | ;A szegmens vege. |
| End Start | ;A program vege |
A mintaprogramban bemutatásra került a memóriaváltozók használata is. Ezeket a
program egy általunk adatok számára elkülönített részén kell elhelyezni. A
memóriaváltozókat egy címkével azonosíthatjuk (KOORD_X: stb.), amik után egy
kettőspont áll. Ezután meg kell jelölni az adat típusát (db - byte-os, dw - wordös, dd -
doublewordös adat), majd el kell helyezni a tárolandó adatot. Ha egy betut vagy
szöveget idézőjelek közé teszünk, annak ascii kódja tárolódik, így például az "A" helyén
65 lesz letárolva. A programban szerepel még egy új utasítás is. A mul végrehajtása
során ha utána 8 bites adat áll (bl), az al regisztert szorozza meg a megadott regiszter
tartalmával és az eredményt ax-ben kapjuk. Amennyiben 16 bites adattal szorzunk (bx),
az AX regiszter tartalma szorzódik és az eredményt DX és AX regiszterekben kapjuk. A
magasabb helyiértékű részt a dx-ben, az alacsonyabbat az ax-ben. Tehát ha például ax
regiszter tartalma 26e5h bx tartalma pedig 76ah akkor a mul bx végrehajtása során ax
regiszterben 5dd2h dx-ben pedig 0120h értéket kapnánk. A programban a szorzást a
karakter memóriacímének kiszámítására használtuk a 2. program előtt leírtak szerint. A
regiszter nullázására és a 2-vel való szorzásra később majd egyszerűbb módszert is
láthatunk. Az utasításnál egy dologra kell vigyázni, hogy a számmal való szorzás nem
megvalósítható (mul 3), de ennek a kivételével bármilyen adatot használhatunk
szorzónak. Található még egy új utasítás is a szövegben, az add összeadó művelet.
Ennek lényege, hogy az első operandushoz adja a másodikat. A mov utasításnál leírtak
itt is érvényesek illetve itt is legalább az egyik tagnak regiszternek kell lennie.
A következő példában egy szöveg pozicionált kiíratását mutatom be. Ez annyiban
különbözik az előzőtől, hogy itt nem elég egy karaktert kiolvasni, hanem egy
meghatározott szöveget végig ki kell írni. Ennek két megoldása lehetséges, az egyik,
hogy megszámoljuk hány betut akarunk kiíratni és egy ciklus segítségével írjuk a
képernyőre a szöveget, de ennek a módszernek hátránya, hogy ha megváltoztatjuk a
szöveget, a ciklus hosszát is változtatni kell. A másik módszer, hogy a szöveg végére
elhelyezünk egy olyan kódot, amit a szövegben biztos hogy nem használunk pl.: 255 és a
kiíratáskor figyeljük, a kirakandó karakter kódját. Ha nem 255, akkor kitehető, ha az,
akkor vége a kiíratásnak. Ügyelni kell, hogy egy betu kirakása után a következő
karaktert kell olvasni, és a következő karakterpozícióba kell tenni azt.
| Pelda04 | Segment | ;Szegmensdefinicio. |
| assume cs:Pelda04,ds:Pelda04 | ;Cs es ds regiszterek bealli- | |
| ;tasa a szegmens elejere. | ||
| Start: | mov ax,Pelda04 | ;A ds regiszter beallitasa. |
| mov ds,ax | ||
| mov ax,0b800h | ;A kepernyomemoria szegmens- | |
| mov es,ax | ;cimet es regiszterbe tolti. | |
| mov al,byte ptr [KOORD_Y] | ;Al regiszterbe tolti a | |
| ;KOORD_Y cimke alatt tarolt | ||
| ;erteket. | ||
| mov bl,160 | ;Bl-be 160-at tolt, mivel | |
| ;egy sor 160 byte. | ||
| mul bl | ;Al erteket megszorozza bl | |
| ;erekevel. | ||
| mov di,ax | ;Az igy kapott eredmenyt | |
| ;di indexregiszterbe tolti. | ||
| mov al,byte ptr [KOORD_X] | ;A vizszintes pozicio erteket | |
| ;al regiszterbe tolti | ||
| mov bl,2 | ;es megszorozza 2-vel | |
| mul bl | ||
| add di,ax | ;majd hozzaadja di-hez. | |
| mov ah,byte ptr [SZIN] | ;Ah-ba a szinkodot tolti. | |
| mov si, offset SZOVEG | ;Si-be a szoveg offsetcimet | |
| ;tolti. | ||
| .1_Pelda04: | mov al,[si] | ;Al regiszterbe az si alltal |
| ;mutatott cimen levo adatot | ||
| ;tolti. | ||
| cmp al,255 | ;Al erteket osszehasonlitja | |
| ;255-el. | ||
| jz Vege | ;Ha egyezik, ugrik a Vege | |
| ;cikehez. | ||
| mov es:[di],ax | ;Az es:di alltal mutatott | |
| ;cimre irja ax tartalmat azaz | ||
| ;a fekete alapon feher "A" | ||
| ;betut. | ||
| add di,2 | ;A kovetkezo kepernyopozicio | |
| inc si | ;A kovetkezo betu. | |
| jmp .1_Pelda04 | ;Ugrik a .1_Pelda04 cimkehez. | |
| Vege: | mov ax,4c00h | ;Kilepes a DOS-ba. |
| int 21h | ||
| KOORD_X: | db 30 | |
| KOORD_Y: | db 12 | |
| SZOVEG: | db "A kiiratando szoveg",255 | |
| SZIN: | db 7 | |
| Pelda04 | Ends | ;A szegmens vege. |
| End Start | ;A program vege |
Ez a program már egy teljes szöveg kiíratását el tudja végezni. Innen már csak egy
lépés lenne különféle vezérlőkódokat beleiktatni a szövegbe, és így lehetőség lenne
például a képernyő-pozíció letárolása a szövegben illetve lehetne több mondatot kiíratni
különböző helyekre, mindössze annyit kell tenni, hogy elhelyezni a vezérlőkódot, amit a
programból figyelünk, és utána az új koordinátákat amiből a program kiszámolja a
szöveg címét. De ezt a feladatot már az olvasóra bízom, az eddig használtakon kívül más
utasítás nem szükséges a program megírásához. Ebben azonban szerepel öt új dolog is.
A legegyszerűbb a címkék használata. Ezek hasonlítanak a memóriaváltozóknál használt
címkékhez, csak ezeket nem adattárolásra használjuk, hanem általában ugráshoz, mint
azt például a jmp .1_Pelda04 sor is teszi. Fontos, hogy a címkék után kettőspontot kell
tenni. Kivételt képeznek a szegmens nevek, illetve a memóriaváltozók, ha az
adatszegmens nem egyezik meg a kódszegmenssel. A jmp egy feltétel nélküli
vezérlésátadó utasítás. Ha a program ehhez a sorhoz ér, a végrehajtást az utasítás után
megadott helyen folytatja. Ez lehet egy címke mint jelen esetben, de lehet egy regiszter
is (si, di, bx) vagy a jmp far utasítás segítségével egy másik szegmensbe is
átugorhatunk, mivel a normál jmp-vel csak az adott 64K-n belül ugrándozhatunk.
A kiíratás során sor kerül a karakterkód vizsgálatára is a cmp utasítással, ami két
érték összehasonlítására szolgál. Használata során először az az adat áll, amit össze
akarunk hasonlítani és utána amivel. A dolog működése tulajdonképpen egy kivonáson
alapszik, amit a gép csak magában végez el, a regiszterek tartalmát nem változtatja
meg. E művelet elvégzése után a flag regiszter egyes bitjei az eredménytől függően
állnak be. A leggyakrabban használt két jelzőbit a carry és a zero. A carry az
úgynevezett átviteli jelzőbit értéke 0 ha a második szám nem nagyobb az elsőnél, azaz
ha az első számból kivonnánk a másodikat nem negatív számot kapnánk. Ha az értéke 1,
akkor az eredmény negatív tehát a második szám az összehasonlítás során nagyobb volt.
A másik jelzőbit a zero, értéke akkor 1, ha a kivonás eredménye nulla lenne, azaz a két
szám azonos. Minden más esetben értéke 0. Ezeket a jelzőbiteket különböző módon
tudjuk vizsgálni. Az egyik lehetőség a feltételes elágazás. A jz csak akkor ugrik a
megadott helyre, ha a z bit értéke 1. Ha a bit 0 értékét szeretnénk figyelni, akkor a jnz
utasítást kéne használni. Ezeknél a feltételes ugrásoknál figyelembe kell venni, hogy ezek
úgynevezett relatív ugrások azaz előre és visszafelé is 127 byte-ot tudnak ugrani
alapesetben. Ez a legtöbbször elegendő, azonban ha mégsem, akkor más megoldáshoz
kell folyamodnunk.
A programban szerepel meg egy egyszerű de új dolog, az inc. Ez nem csinál mást,
mint növeli eggyel az utána álló operandus értékét. Ez lehet regiszter, illetve
memóriatartalom is. Az inc utasítás párja a dec ami csökkenti eggyel az utána álló adat
értékét.
Egy szintet vissza, vagy
vissza a főmenübe.