• Nem Talált Eredményt

Adatok deklarálása

In document Az ábrák listája (Pldal 192-195)

A táblázatok listája

2. Az assembly program felépítése

2.4. Adatok deklarálása

Ezek után térjünk rá az adatterület és a kódterület szétválasztásának technikájára. A „.data” direktívával azt közöljük a fordítóval, hogy minden egyes hivatkozás, deklaráció, amit ez után írunk, az adatterületen kerül létrehozásra. Tudnunk kell, hogy assembly program kód része sohasem keveredik össze a programban használt adatokkal, kódokban nem lehetnek adatok, adatokban pedig általában kódok. A kódterületet a kódszegmens, az adatterületet az adatszegmens regiszter jelöli ki, ezeket a futtató rendszer kezeli, nincs rá hatásunk. Persze ettől kellő hozzáértéssel el lehet térni, lesznek „trükkös” megoldásaink, amikor magunk, futási időben fogjuk írni a kódterületet, adatokat helyezünk el rajta, majd a korábban, mint tárolt „adatokra” később, mint végrehajtható

„kódokra” adjuk rá a vezérlést, de ezek nem szabványos megoldások, és tanácsos őket elkerülni, mert nehezen érthető és karbantartható programokat, rendszereket eredményeznek.

Az assembly nyelvben kétféle hivatkozás (szimbólum) van, az egyik a változó, a másik az utasításcímke. Az adatterületen változókat deklarálhatunk, ez egy kicsit eltér a magas szintű programnyelvekben megszokott deklarációtól, először a változó nevét adjuk meg, legyen ez pl. tesztadat (A kis/nagybetűre vigyázzunk!), a továbbiakban ezen a néven hivatkozhatunk rá.

Ezután az adattípus meghatározása következik. Sokféle adattípus szóba jöhet, ezek közül a legkisebb egység a byte. Tulajdonképpen itt nem a megszokott értelemben vett adattípust határozzuk meg, hanem fogjuk fel úgy, hogy azt mondjuk meg, hogy változónk egyedi példánya mekkora egységet (egységeket) foglal le a memóriában.

Ugyanebben a sorban kezdőértéket is adhatunk a változónknak. Tehát a

jelentése: változónk neve teszt lesz, ez egy 1 bájtos változó, 0x12 kezdőértékkel. Ekkor a fordító lefoglal a teszt adatunknak 1 bájtot, és a lefoglalt területre beteszi a 0x12 értéket. Legyen egy másik változónk is:

Ekkor, közvetlenül a teszt adat bájtja után a fordító egy szónyi (2 bájtnyi) területet foglal, és beleteszi az 0x5678-at. (Fordított sorrendben!!!). Ha a teszt adat kezdőcíme a 0100 lenne, akkor a tesz2 adat a 0101 címen helyezkedne el.

Módosítsunk egy kicsit a deklaráción:

A teszt adat most 4 darab bájtból áll a megfelelő értékekkel, és utána jön a teszt2 1 szavas (2 bájtos) adat. Ha a teszt adat kezdőcíme 0100, akkor a teszt2-é 0104. Pontosítsuk a fenti definíciónkat, a byte (word, dword,…) jelentése: változónk bájt(szó,duplaszó,…) méretű adatokból áll egészen addig, míg a következő szimbólum nem következik.

Lehetőség van arra is, hogy egy deklarációban egyszerre több egyedi példány számára foglaljunk le helyet úgy, hogy nem felsoroljuk őket hanem egy külön az erre a célra szolgáló direktívával határozzuk meg. Ez a DUP, melynek használata az őt követő zárójelek közötti inicializálási és az őt megelőző mennyiségi mutató

Térjünk vissza a programunk írására, tehát a következő sorunk a:

A fordító ennek hatására bájtos adatonként a karaktereknek a kódját (ASCII kód) helyezi el a memóriában, abban a sorrendben, ahogyan felsoroltuk, tehát először a ’E’ kódja, utána a ’z’ kódja, és így tovább. Az idézőjelbe tett sztring után vesszővel elválasztva további bájtokat is megadhatunk, esetünkben a 13, 10, 0-kat.

Tudnunk kell, hogy azokat a karaktersorozatokat, amiket 0-val zárunk, 0-val terminált sztringnek is értelmezhetjük, úgy gondolhatjuk, hogy egy összefüggő szövegfolyamról van szó, melynek a végét a 0 jelenti.

Magában az adatban nincs meghatározva a sztring hossza, azt nekünk kell meghatározni úgy, hogy végiglépegetünk ezen a karaktersorozaton és megkeressük a 0-t, ott van a sztringünk vége.

Nos, tehát létrehoztunk egy olyan változót, melynek neve tesztadat, típusa byte és a fenti karaktersorozatból áll.

2.4.2. Inicializálatlan adatterület

A következő lehetőség, hogy olyan adatokat hozunk létre, amelyeket nem inicializálunk, nem adunk neki kezdőértéket. Az előbbiekben a tesztadat pontosan megfelel annak a bájtos karaktersorozatnak, amit byte után írtunk.

Nem kötelező mindig előre meghatározni az adattartalmat, előfordul, hogy egy változónak csak a programunk futása során adunk értéket. Ekkor a „.data?” direktívát adjuk meg, a „?”-et az inicializálatlan változók jelölésére használjuk.

Amennyiben a változók után nem írunk kérdőjelet, a fordítás során hibaüzenetet kapunk.

Természetesen az inicializált és az inicializálatlan adatunkból is tetszőleges számú lehet.

A „.data” és a „.data?” direktíva bárhol elhelyezhető a programunkban, a fordító össze fogja azokat szerkeszteni egyetlen adatterületté, mely élesen különválik a kódterülettől.

2.4.3. Konstansok

2.4.3.1. Szimbolikus konstansok

Szimbolikus konstansokat programunk írása során azért használunk, hogy kódunkat jobban olvashatóvá tegyük.

Az „equ” vagy az „=” direktívával definiálhatóak, mely után értéket is rendelhetünk a szimbólumhoz. Az „=”

direktívával hozzárendelt értéket a kódunkban később felülírhatjuk, az „equ”-val adottat viszont nem. Amikor a kód írása során használjuk a konstansra hivatkozó címkét, a fordító egyszerűen behelyettesíti a megadott értéket a címke helyére. Szokás a konstansokat a forráskód áttekinthetősége miatt csupa nagybetűvel jelölni.

2.4.3.2. „.const” direktíva

A „.const” direktíva után deklarált változóink a futás során olyan területen jönnek létre, mely a program számára csak olvasási engedéllyel rendelkezik, ezért, ha megpróbáljuk kódunkban módosítani a változó értékét, az ismert

„Acces Violation” hibaüzenetet kapjuk.

2.5. Kódterület

Ha most leírjuk a „.code” direktívát, akkor elkezdhetjük írni a programkódokat, innentől a fordító kódokat fog értelmezni. Erre a területre már nem írhatunk változó deklarációt, mert akkor hibaüzenetet kapunk. Ha másik változót szeretnénk deklarálni, akkor ismét használnunk kell a „.data” vagy a „.data?” direktívát, deklarálni a változót, majd a „.code” direktívával visszatérni a kódterületre.

A következő sorban egy „start” nevű címkét fogunk használtunk, itt kezdjük el írni a kódunkat. Rögtön utána egy „nop” következik (No operation, üres utasítás). Ettől kezdve már valójában programozunk, vagyis ez a

„nop” már egy utasítás, mely a processzort egy művelet végrehajtására kéri fel, éppen arra utasítja, hogy ne csináljon semmit, hanem vegye a következő utasítást.

Használunk még egy „nop” utasítást, ennek az az oka, hogy a címkével jelölt sorokban nem tudunk ún.

töréspontot elhelyezni.

A töréspont egy adott pontja a programunknak, ahol megállíthatjuk a végrehajtást, és az eddigi futás eredményét ellenőrizhetjük, mik a regisztertartalmak, mi a változóink értéke, stb. (E nélkül ma már szinte lehetetlen fejleszteni).

Az al és a bl regiszterekbe bemozgattuk a korábban deklarált konstansokat (figyelem, csupa nagybetűvel, ahogyan deklaráltuk!), majd összeadtuk őket és az eredményt az al regiszterbe helyeztük el.

Írtunk még egy „inkey” utasítást is. Ennek hatására a program futása felfüggesztődik, míg a felhasználó a konzol ablakban meg nem nyom egy billentyűt. Az „inkey” utasítás tulajdonképpen egy makró. A makrók olyan kódrészletek, melyeket előre megírtak nekünk, és vagy paraméterezhetők, azaz megmondhatók, hogy milyen értékekkel alakítsuk a magunk igényeire, vagy direkt módon behelyettesítenek egy kódrészletet. Valójában egy kódrészlet teljes egészében idemásolódik, a lépésenkénti végrehajtás során látni fogjuk, hogy mi helyettesítődik be ennek az egyetlen sornak a helyébe.

Utolsó utasításunk egy „exit”, ami szintén egy makró, a program szabályos lezárását eredményezi.

Az assembler programot kötelezően az „end” direktívával kell lezárnunk. Az „end” direktíva után lévő utasítások nem hajtódnak végre. Az „end” direktíva paramétere programunk kezdőcímkéje, jelen esetben a

„start”. A futtató környezet ebből a paraméterből azonosítja a programunk belépési pontját, vagyis innen kezdi el futtatni a programot.

In document Az ábrák listája (Pldal 192-195)