Assembly tételkidolgozás 2017 ViczeZoltán
Operatív memória Felépítése –Alapja a bit: bit: 0 vagy 1 érték érték –Bitek rendszerint rendszerint csoportosítva csoportosítva kerülnek feldolgozásra feldolgozásra
•Cella: legkisebb címezhető egység •8 bit = 1 bájt •Lehetnek más, pl. 4, 16 vagy más csoportosítások is! –A memória memória bájtok sorozata sorozata –Bájtok elérése elérése a címükkel címükkel
Bájtok értékeinek értelmezése –Lehet adat és program is!
•Adat: ASCII, UTF, BCD, kettes komplemens, lebegőpontos, … •Gépi kód: a számok utasításokat jelentenek –A CPU csak ezeket az utasításokat tudja végrehajtani! –Magasabb szintű programozási nyelvekről gépi kódra kell fordítani. –Akár önmódosító önmódosító program program is készíthető •Veszélyes! –Hibás működés, ha adatrészre kerül a vezérlés! •A mai modern operációs rendszerek védik a kódterületet –Ez elősegíti a virtuális memória hatékonyabb kezelését is
Gépi kód –Numerikus gépi nyelv –Az utasítások és az operandusok számok –1 utasítás 1 vagy több bájton kódolódik –Elemi műveletek végrehajtására
Assembly nyelv –A numerikus gépi nyelv szimbolikus formája –Mnemonik: –Mnemonik: emlékeztető kód a numerikus utasítások helyett –Szimbolikus nevek és címek –Makrók –Feltételes –Feltételes fordítás fordítás
Assembler –A fordító, amely assembly nyelvről gépi kódra fordít
Disassembler –Gépi kódból kódból mnemonik mnemonik kód listázása listázása –Vigyázni kell, hogy a listázás kezdőcíme valóban utasításhatáron legyen! –Ha szimbólumlista elérhető, akkor Assembly-szerű lista kapható
Assembly nyelv alkalmazásának előnyei és hátrányai. •Hátrányok –Nehézkes, időigényes, sok hibalehetőség –Hosszadalmasabb hibakeresés, karbantartás –Architektúrák közötti portabilitás hiánya •Előnyök –Hatékonyság –Hatékonyság –A hardver teljes elérhetősége •Bizonyos regiszterek magas szintű nyelvekből nem használhatók •Hardver elemek közvetlen vezérlése •Játékprogramok, •Játékprogramok, eszközmeghajtók, eszközmeghajtók, …
Forráskód –Forrásnyelvből célnyelvre alakít, pl.: •C++, C-> tárgykód (.o/.obj) •Assembly -> tárgykód •Java -> classfájl •C -> Assembly (.asm) •FORTRAN -> C
Tárgykód • • •
.obj: DOS, Windows Unix, Linux, Cygwin, … .o: Fordító- specifikus formátum! –Azonos kiterjesztés még nem jelenti azt, hogy összeszerkeszthetők!
–Végrehajtható (futtatható) • • • • • •
.com: kis méretű DOS alkalmazások .exe: DOS, Windows formátum (többféle szerkezet!) .dll: dinamikusan szerkeszthető (Windows) Unix-alapú rendszereknél nincs futtatható kiterjesztés, azt a fájl jogosultsága mondja meg dinamikusan szerkeszthető (Unix, Linux, …) .so: .a: statikusan szerkeszthető tárgykód gyűjtemény (Unix, Linux…)
Közvetlenül –B/K kapuk írása/olvasása –Közvetlenül a hardverrel kommunikálunk –A mai modern operációs rendszerek ezt tilt(hat)ják –Előnye a hatékonyság (pl. játékprogramok konzolokra) –Hátránya, hogy hardver eszközönként/gyártónként más kommunikáció szükséges!
BIOS rendszeren keresztül –BIOS gyártó specifikus lehet, de egységesebb a kezelése –Operációs rendszertől független, de túlságosan alapszintű hozzáférés, speciális hardver opciók esetleg nem érhetők el így Operációs rendszeren keresztül –„HAL” (Hardware Abstraction Layer): Hardver absztrakciós szint bevezetése –Adott típusú eszközök esetén egységes programozási felület. Könnyebb sokféle hardvert támogató szoftvert készíteni. –Az absztrakciós szint miatt kevésbé hatékony! –Meghajtó-programokon (driver) keresztül
•Rosszul megírt driver miatt összeomolhat a rendszer! •Harmadik féltől származó kódok esetén digitális aláírás fokozhatja a megbízhatóságot Függvénykönyvtárakon keresztül –Felhasználói program szinten –Újabb absztrakciós szint a programunk és az operációs rendszer/BIOS/hardver között
x86 32-bites üzemmódok Valós mód –8086/8088-ként működik –Max. 1 MB memória címezhető Védett mód (32-bit) –A CPU lehetőségeinek teljes kihasználása •Védelmi mechanizmusok, gyorsítótár, virtuális memóriakezelés , … –Négy privilegizált szint (FLAG bitek vezérlik) •0-s szint: kernel mód (operációs rendszer) •1-es, 2-es szint: ritkán használt •3-as szint: felhasználói programok Virtuális 8086 mód –Párhuzamosan több valós módú virtuális gép futhat –Védett módú környezet vezérli –Ha „lefagy” a virtuális gép, visszatérhetünk az indító környezethez
Operatív memória felépítése –Bit: Alapegység, 0 vagy 1 érték –Cella: Legkisebb címezhető egység (8 bit = 1 bájt) –Szó: 16 bit (2 bájt) –Paragrafus: 16 bájt, 16-tal osztható címen kezdődik –Lap: 256 bájt, 256-tal osztható címen kezdődik –x86 bájt sorrend: kis-endián (Több bájtos reprezentációknál a legkisebb helyértékű bájt szerepel alacsonyabb memóriacímen)
–Negatív számok kettes komplemens alakban
Szegmensek –A memória részekre osztva érhető el –Valós módban bármi szabadon olvasható és felülírható
•Akár az operációs rendszer kódja is… –Védett módban a hozzáférést jogosultságok szabályozzák •Adat és kód esetén is •Jogosulatlan hozzáférés esetén hiba! –Processzor detektálja, operációs rendszer kezeli
Szegmens típusok Kódszegmens(ek) –A program utasításait tartalmazza Adatszegmens(ek) –Konstansok, változók, struktúrák, tömbök területe Veremszegmens –Minden processzus saját vermet kap –LIFO adattárolási elv • ast n irst ut: amit utoljára tettünk bele, az vehető ki először –Kulcsfontosságú a megfelelő működéshez! •Eljáráshíváskor visszatérési cím tárolása •Eljáráshíváskor paraméterátadás •Lokális változók létrehozási helye •Adatok ideiglenes mentése pl. megszakításkezeléskor
Védett flat modell jellemzői
Általános célú regiszterek –EAX: Akkumulátor; alsó szava AX , annak alsó és felső bájtja AL és AH Egyedi szerep szorzásnál és osztásnál
–EBX: Bázis (címzés); alsó szava BX, annak alsó és felső bájtja BL és BH Egyedi szerep memóriacímzésnél (valós módban)
–ECX: Számláló; alsó szava CX, annak alsó és felső bájtja CL és CH Egyedi szerep bitléptető, sztring és ismétléses műveleteknél –EDX: Adat; alsó szava DX, annak alsó és felső bájtja DL és DH Egyedi szerep szorzásnál és osztásnál
–EBP: Bázis mutató; alsó szava BP Egyedi szerep verem indexelt címzésére –ESI:
Forrás index; alsó szava SI Egyedi szerep sztring műveleteknél és memóriacímzésnél (valós mód)
–EDI:
Cél index; alsó szava DI Egyedi szerep sztring műveleteknél és memóriacímzésnél (valós mód)
– –
: Utasítás számláló (csak vezérlésátadással írható felül) : CPU állapotát jelző bitek összessége •C (Carry): Átvitel előjel nélküli műveleteknél •P (Parity): Az eredmény alsó 8 bitjének paritása •A (Aux Carry): Átvitel a 3. és 4. bitek között (BCD számoknál) •Z (Zero): 1 (igaz), ha az eredmény 0, különben 0 (hamis) •S (Sign): Az eredmény legmagasabb helyiértékű bitje (előjel) •T (Trap): 1: debug mód, 0: automatikus •I (Interrupt): 1: maszkolható megszakítás engedélyezve, 0: tiltva •D (Direction): Sztring műveletek iránya 1: csökkenő, 0: növekvő •O (Overflow): Előjeles túlcsordulás
(CodeSegment): kód szegmens (Data Segment): adat szegmens (Extra Segment): (másodlagos) adat szegmens (Stack Segment): verem szegmens
: extra adat szegmens (csak védett módban) : extra adat szegmens (csak védett módban)
Közvetlen címzés (operandus) az –Vagyis a kódterületen van, értéke nem változhat –Az
MOV AX, 07FFH MOV CL, 34H
; AX tartalma 07FFH lesz ; CL 34H lesz, ; CH nem változik meg! ; Ha CX 1256H volt, akkor ; ezután 1234H lesz.
Direkt memóriacímzés az utasítás része –Assembly kódban használunk –Az (méretének) egyezni kell! –Az
ADAT DW 34F2H
; 1 szóhossznyi adat
;... MOV AX, ADAT MOV AX, [ADAT]
; AX tartalma 34F2H lesz ; ez is ugyanaz
Regiszter indirekt címzés –A címzéshez használt [regiszter] értéke adja az operandus memóriacímét –EAX, EBX, ECX, EDX, ESI, EDI, EBP használható
•EBP vagy BP használata esetén a verem szegmens, minden más esetben az adat szegmens kerül címzésre! –16-bites esetben csak BX, BP, SI, DI lehet a regiszter MOV EAX, [EDI] ; EAX tartalma az EDI értéke szerinti memóriacímen lévő 32-bites egész érték lesz MOV [EDI], AX
; Az EDI értéke szerinti memóriacímen tárolásra kerül AX 16-bites tartalma
Regiszter relatív címzés –Az utasításban elhelyezett számot (konstans elto lás) hozzáadja a kiválasztott [regiszterhez]
•EAX, EBX, ECX, EDX, ESI, EDI, EBP •16 bites esetben csak SI vagy DI lehet! MOV AX, 07FH[ EDI ] MOV [ EDI + 07FH ], AX
; AX tartalma EDI + 7FH memóriacím szavas tartalma lesz ; AX értéke a fenti memóriacímre kerül
Bázis-index relatív címzés –
+
+
adja a címet
MOV AX, 057FH[ ESI ][ EBX ] MOV AX,[ EBX + ESI + 057FH ]
; AX értéke ESI + EBX + 057FH címen ; található szó értéke lesz ; ugyanaz
Skála-index címzés adja a címet
•Eltolás lehet fordítási időben számítható kifejezés, de el is hagyható •Skála lehet: (1,) 2, 4, vagy 8 •16-bites változata nincs! –Ideális 1- és 2- dimenziós tömbök indexelésére •1D tömb: Tömb kezdőcíme a bázis, skála a tömbelem típusának mérete, az index az elérendő elem sorszáma (0- bázisú) •2D tömb: Eltolás a tömb kezdőcíme, bázis a sor kezdőcíme, skála a tömbelem típusának mérete, index az oszlop száma (0-bázisú) MOV AX,[EBX+2*ESI]
Összefoglaló táblázat
MOV utasítás MOV op1, op2 –op2 tartalma op1-be –Legalább az egyik operandus regiszter kell legyen –op1 és op2 bitszélességének egyezni kell
MOVZX utasítás MOVZX op1, op2 –op2 tartalma op1-be
•op1 16 vagy 32 bites regiszter kell legyen! •op2 memóriacím vagy regiszter •op2 bitszélessége kisebb, mint op1! –op1
MOVSX utasítás MOVSX op1, op2 –op2 tartalma op1-be
•Mint MOVZX-nél –op1 magasabb helyi értékű bitjei az előjel értékét veszik fel!
PUSH, POP PUSH op – Operandus értéke a verembe kerül
• Regiszter vagy memóriacím értéke, vagy konstans – Csak 16 vagy 32 bites érték mozgatható! POP op – A verem tetejének értéke op-ba kerül – Csak 16 vagy 32 bites érték mozgatható!
FLAG regiszter mentése –PUSHF, POPF • FLAGS regiszter (16 bites) tartalma kerül a verembe, illetve onnan visszaolvasásra –PUSHFD, POPFD
• EFLAGS regiszter (32 bites) tartalma kerül a verembe, illetve onnan visszaolvasásra Általános célú regiszterek mentése –PUSHA, POPA • Az összes 16 bites általános célú regiszter tartalma kerül a verembe, illetve onnan visszaolvasásra (AX, BX, CX, DX, SP, BP, SI, DI) –PUSHAD, POPAD • Az összes 32 bites általános célú regiszter tartalma kerül a verembe, illetve onnan visszaolvasásra (EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)
Bájtos, szavas és duplaszavas adatokra •Forrás adat: – helyett más szegmens regiszter is használható •Cél adat: – rögzített, nem definiálható felül! •Irány – flag tartalma alapján a memóriacím automatikusan változik •Ha = 0, akkor növelés ( utasítás) •Ha = 1, akkor csökkenés ( utasítás)
CMPSB, CMPSW, CMPSD, CMPS are tring yte/ ord/ oubleword
– o – – –
cím tartalmával által címzett bájt/szó/duplaszó összehasonlítása regiszter bitjei a utasításnak megfelelően állnak be és
értéke a flag szerint változik
–
•Működése analóg a
utasításéval
–MOVS esetén
•Két operandus is kell! •Az operandusok típusa dönti el, melyik utasítást kell használni, de ESI és EDI alapján másol! •Így definiálható felül a forrás szegmens regiszter •Használata nem célszerű!
LODSB, LODSW, LODSD, LODS –
tring yte/ ord/ oubleword
a
–
cím tartalma
–Csak
/
/
regiszter változik,
-be kerül nem
működése analóg a
–
utasításéval
STOSB, STOSW, STOSD, STOS – –
re tring yte/ ord/ oubleword /
/
–Csak –
tartalma
címre kerül
regiszter változik,
nem
működése analóg a
utasításéval
REP –
eat
– Nem önálló utasítás! (
)
– Sztring művelet előtt helyezhető el
Működése
– Ismétlés számát –
– –
-be töltjük
sztringművelet • Művelet végrehajtása, és/vagy léptetése csökkentése • • Ha nem 0, akkor ismétlés műveletek előtt alkalmazva és -vel (és -vel) egyenértékű a hatása! • -vel használni nincs értelme
AND, OR, XOR –Logikai ÉS, VAGY, KIZÁRÓ VAGY művelet az operandusok bitjei között –A „szokásos” igazságtáblák szerint –Eredmény op1-be
AND op1, op2
NOT –Operandus bitjeit negálja (egyes komplemens)
NOT op –(Kettes komplemens: NEG utasítás (aritmetikai művelet))
TEST –Logikai ÉS művelet az operandusok között, de csak a flag-ek állítódnak, az operandusok változatlanok
maradnak! –Általában 1 bit tesztelésére használatos TEST op1, op2
ADD Előjeles (kettes komplemens), –
flageket állítja
; EAX = EAX + EBX
ADD EAX, EBX
ADC Előjeles (kettes komplemens), flageket állítja – flag bit értékét is hozzáadja az összeghez
; AL = AL + AH + C
ADC AL, AH
SUB Előjeles (kettes komplemens), –
flageket állítja
; EAX = EAX - EBX
SUB EAX, EBX
SBB Előjeles (kettes komplemens), flageket állítja – flag bit értékét is kivonja
; AL = AL - AH – C
SBB AL, AH
MUL Előjeltelen szorzás. A szorzó és a szorzandó méretének mindig meg kell egyeznie és a szorzat mindig ennek a méretnek a kétszerese. A három formátum elfogad regisztert és memória címet is operandusként, viszont sosem közvetlen operandust (konstanst): MUL reg/mem8 MUL reg/mem16 Szorzandó Szorzó Szorzat AL reg/mem8 AX MUL reg/mem32 reg/mem16 AX DX:AX EAX
MUL BL
; AX = AL * BL
reg/mem32
EDX:EAX
IMUL Előjeles szorzás. Működése hasonló a MUL utasításhoz, azzal a különbséggel, hogy az IMUL megőrzi a szorzat előjelét. Az x86-os utasítás halmaz három különböző formátumát támogatja az IMUL utasításnak: egy-, kettő-, illetve háromoperandusos verzió. Egyoperandusos
IMUL CL
; AX = AL * CL
eredmény az AX / DX:AX / EDX:EAX – ben képződik
; AX = AX * BX
eredmény az első operandusban képződik
; AX = BX * 6
eredmény az első operandusban képződik
Kétoperandusos IMUL AX, BX
Háromoperandusos IMUL AX, BX, 6
DIV A DIV ( ) utasítás használható 8, 16 és 32 bites verzióban is. Egyetlen operandusa van, az osztó, ami lehet egy regiszter vagy egy memória cím. A szintaxisa: DIV reg/mem8 Osztandó Osztó (operandus) Hányados Maradék DIV reg/mem16 reg/mem8 AL AX AH DIV reg/mem32 DX:AX AX DX reg/mem16 EDX:EAX
DIV BL
reg/mem32
; AL = AX / BL
EAX
EDX
, AH (maradék)
IDIV közel megegyezik az előjelnélkülivel, egy fontos különbséggel: az osztandó előjel kiterjesztett kell, hogy legyen még az osztás elvégzése előtt. Az előjel kiterjesztés azt jelenti, hogy átmásoljuk a szám legfelső bitjét az összes felsőbb bit helyére az adott változóban vagy regiszterben. Az
Szükség esetén az osztandó bitszélességét előjelhelyesen ki kell terjeszteni! –Például egyező méretű osztandó és osztó esetén –Előjel nélküli esetben kiterjesztés 0 bit értékkel •AH, illetve DX, EDX tartalma –Előjeles esetben minden bitet az előjel bit értékével
CBW (Convert Byte to Word)
–Bájtból előjelhelyes szó feltöltése regiszter előjele alapján •Negatív esetben lesz , egyébként CWD (Convert Word to Double Word) –Szóból előjelhelyes dupla szó, : – regiszter előjele alapján feltöltése lesz , egyébként •Negatív esetben –
•CWDE (Convert Word to Extended Doubleword)
-re regisztert egészíti ki előjelhelyes lesz •Negatív esetben felső két bájtja, egyébként •CDQ (Convert Doubleword to Quadword) – előjele alapján feltöltése előjelhelyes 64-bites értékre –
SHL (Shift Left) Az SHL utasítás logikai léptetést végez balra a cél operanduson belül, az alsó biteket feltöltve nullával. A legmagasabb helyiértéken lévő bit bekerül a Carry flag-be, és ami addig a Carry flag-ben volt eldobódik. A forrás operandusban adhatjuk meg, hogy hány bittel szeretnénk arrább léptetni. MOV AL, 8Fh SHL AL, 1
; AL = 10001111b ; AL = 00011110b mivel 1 bittel balra tolódott ;C=1
SHR (Shift Right) Az SHR (SHift Right) utasítás logikai léptetést végez jobbra a cél operanduson belül, a felső biteket feltöltve nullával. A legalacsonyabb helyiértéken lévő bit bekerül a Carry flag-be, és ami addig a Carry flag-ben volt eldobódik. A forrás operandusban adhatjuk meg, hogy hány bittel szeretnénk arrább léptetni.
MOV AL, 0D0h SHR AL, 1
; AL = 11010000b ; AL = 01101000b mivel 1 bittel jobbra tolódott ;C=0
ROL A ROL utasítás hasonlít az SHL utasításhoz, azzal a különbséggel, hogy itt körkörösen mozognak a bitek balra. A legmagasabb helyiértéken lévő bit beleíródik a Carry flag-be is és a legalacsonyabb helyiértékű bit helyére is. MOV AL, 8Fh ROL AL, 1
; AL = 10001111b ; AL = 00011111b mivel 1 bittel balra tolódott ; körbe. C = 1
ROR A ROR utasítás hasonlít az SHR utasításhoz, azzal a különbséggel, hogy itt körkörösen mozognak a bitek jobbra. A legalacsonyabb helyiértéken lévő bit beleíródik a Carry flag-be is és a legmagasabb helyiértékű bit helyére is. MOV AL, 0D1h ROR AL, 1
; AL = 11010001b ; AL = 11101000b mivel 1 bittel jobbra tolódott ; körbe. C = 1
Direkt –Az utasítás tartalmazza EIP és CS új értékét
EIP-relatív –Előjeles egész érték hozzáadása az utasítás-számlálóhoz –Ha negatív, akkor „visszafelé” ugrunk –A szegmensen belül körkörös a címzés
•Ha a szegmens végén ugrunk előre, túl a szegmens határán, akkor a szegmens elején „találjuk magunkat”
Indirekt (regiszter vagy memória címzés) –EIP új értéke egy regiszter értékét veszi fel –Címzéssel elért memóriaterület adja meg EIP és CS új értékeit (pl. ugrótábla elemeit címezzük)
•Rövid ugrás –EIP relatív, 1 előjeles bájton ábrázolt távolságra
•Szegmensen belül (CS változatlan marad) [- 128,+127] bájt tartományon belül!
•Ugrás közeli (NEAR) címre –EIP relatív, 4 előjeles bájton ábrázolt távolságra
•Szegmensen belül (CS változatlan marad) [- 2GB,+2GB] bájt tartományon belül!
•Ugrás távoli (FAR) címre –CS és EIP is változik, 6 bájt szükséges
Feltétel nélküli vezérlésátadás Ugrás –Rövid, közeli (
), vagy távoli (
) címre
), vagy távoli (
) címre
–
Eljárás –Rövid, közeli ( –
•Vezérlésátadás a címre, visszatérési cím a verembe –
•Visszatérés a verem tetején található címre –
•Visszatérés, és n darab érték kivétele a veremből •Vermen keresztül átadott paraméterek takarítására –Célszerűbb eljárásokat használni ugrások helyett!
Eljáráshívás utasításai Definíció név
{ [ NEAR ], FAR } ; eljárás törzse
név
–Több belépési pontja is lehet egy eljárásnak
–Ugrás, ha feltétel teljesül –Következő utasítás végrehajtása, ha nem
LOOP címke számláló regiszter csökkentése 1 értékkel, ugrás ha még nem nulla az értéke –Egyébként következő utasítás jön –
cimke:
;... LOOP cimke LOOPNZ, LOOPNE –Ha FLAG értéke 0, akkor csökkentése, ugrás ha az még nem nulla –Egyébként következő utasítás jön –
LOOPZ , LOOPE –Ha FLAG értéke 1, akkor csökkentése, ugrás ha az még nem nulla –Egyébként következő utasítás jön –
Paraméterátadás eljárásnak - Assemblyben az átadás módja nincs szabályozva, a programozónak kell gondoskodnia róla - Magasszintű nyelvekkel kombinált Assembly program esetén a másik nyelv hívási mechanizmusát
kell használni az Assembly részben Történhet – Regiszter(ek)en keresztül • Változó értékek • Memóriaterületek címei • Probléma: globális változók, rekurzió támogatása nem megoldott – Vermen keresztül • Változók értékei, címek a verembe kerülnek • Bázis-relatív címzéssel elérhetők az eljárásban • Rekurzió esetén saját lokális változókészlet használható
Eljáráshívási konvenciók –Különösen publikus DLL-ek, lib-ek készítésekor! –Regiszterekben vagy vermen keresztül? –Ki takarítsa ki a vermet?
•Hívó vagy hívott?
cdecl –C programozási nyelv elvét követi –A
a verembe teszi a paramétereket
•Fordított sorrendben (hátulról előre) –Visszatérés után a •Probléma: minden CALL után plusz takarító kód! –Így valósítható meg hatékonyan változó számú paraméterlista használata (ld. C nyelv, printf()) f(x,y);
push y push x call f
stdcall –Win32 rendszerhívások ezt a konvenciót használják –A
a verembe teszi a paramétereket
–A
takarítja a vermet
•A takarító kód egy helyen jelenik csak meg, nem minden hívásnál fastcall –x64 esetén alapértelmezett –Az első hat paraméter regisztereken keresztül –A többi a vermen keresztül, ha van –Lebegőpontos paraméterek száma
•
regiszterben
–A veremkezelő kódot nem mi írjuk, a fordítóprogram generálja! –Paramétertípusok megadása és alapszintű ellenőrzése! –Jobban olvasható kód, könnyebb hibakeresés!
PROTO –Eljárás nevének, paraméterei típusának megadása –Az eljárás hívása előtt derüljön ki (definíció vagy deklaráció)
PROC –Megadható, hogy •mely regiszterek tartalma kerüljön mentésre és visszaállításra ( ); •eljárás milyen típusú paramétereket vár, milyen sorrendben; •paraméterekhez szimbólumnevek társíthatók ( -relatív címzés helyett).
INVOKE –Paraméterek verembe helyezése • és típus esetén jobbról balra haladva! –Paraméter típusok ellenőrzése / konverziója •Nem kompatibilis típusok esetén fordítási hiba! • direktíva: lokális változók címének átadására (globális esetén == –Verem takarítása eljárásból visszatérés után
)
Memória modell választás + rövid definíció –.MODEL direktíva a program elején
•TINY, SMALL, MEDIUM, COMPACT, LARGE, HUGE, FLAT •Szegmensek számát és maximális méretét adja meg –.DATA, .CODE, .STACK direktívák a programban szegmens definíciókhoz Teljes szegmens definíció –A szegmensek minden adatát megadjuk a definíciókor (név, illesztés, kombinálás, osztály)
Konstans szimbólumok •Csak a fordítónak szól, gépi kódra nem fordul! •Nem módosítható nev EQU kifejezes ABC EQU 25 MOV AX, ABC MOV AX, 25
; egyenértékűek!
Változó szimbólumok •Csak a fordítónak szól, gépi kódra nem fordul! •Értéke újradefiniálható nev kifejezes = –Értéke újabb definícióval felülírható: X = 100 DB X X = 150 DB X
; OK ; helyfoglalás 100 értékkel ; OK ; helyfoglalás 150 értékkel
Kifejezések Alkotóelemei –Szimbólumok –Konstansok –Műveleti jelek –Direktívák
Megkötés –A kifejezéseket a fordító értékeli ki, nem gépi kódra fordulnak! –Csak fordítási időben ismert adatok használhatók!
Kifejezések
•Zárójelek (…) […] •. (pont) struktúrák használatakor •LENGTHOF terület elemeinek száma •SIZEOF terület mérete bájtokban •TYPE egy elem mérete bájtokban EXP DW 100 DUP (1)
;LENGTHOF=100, SIZEOF=200, TYPE=2 •WIDTH rekord mezőszélessége •Szg-reg: –Alapértelmezett szegmensregiszter felülbírálása
MOV AX, ES:[ EBX ] •PTR –Változó méretének felüldefiniálása –BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR
MOV AL, BYTE PTR DATW ; Szavas területről bájt •OFFSET, SEG –Szimbólum offszet és szegmens címe MOV AX, OFFSET DAT1 ; távolság szegmens elejétől •HIGH, LOW –Egy szó felső vagy alsó bájtját címzi DAT DW 1234H MOV AL, HIGH DAT ; AL-be 12 kerül (little endian!) •THIS –EQU-val együtt egy terület többféle típusként lehet definiálva •Szorzás, osztás, maradék operátorok MOV CX, (TYPE EXP)*(LENGTH EXP) MOV AX, 100 MOD 17 ; 15 az eredmény, fordításkor! •Összeadás, kivonás, negálás MOV AX,KONST1+KONST2 •Relációs operátorok –EQ, NE, LT, LE, GT, GE (=, ≠, <, ≤, >, ≥) –Feltételes blokkokban
•NOT; AND; OR; XOR –Nem tévesztendő össze a megfelelő logikai utasításokkal! OR AL, 0AH OR 0DH ; 2. op ford.kor!
Makrók –Meghívásakor a tartalma az adott helyre másolódik
• •Rövid törzs esetén érdemes használni (egyébként eljárást) –Elkerülhető az eljáráshívás plusz időigénye, de nagyobb méretű lesz a kód az ismétlődő kódrészletek miatt –Adat és kódterülethez is használható –A makró paramétereibe behelyettesíti az átadott argumentumok értékeit név MACRO
… ENDM
[par1][, par2, ...]
példa:
MOVE MACRO A, B PUSH AX MOV AX, B MOV A, AX POP AX ENDM
; definíció ; AX mentése
MOVE
; használata
VAR1, VAR2
; AX visszaállítása
–A makró törzsében jelezhetjük a másolás végét
EXITM
• –A név újra használható lesz
PURGE név –A makró minden egyes behelyettesítésekor
ECHO Szöveg
Makróra lokális címke definiálása –Egyébként egy makró többszöri felhasználásakor ugyanaz a címke jönne létre, ami hibát okoz!
READ
READ1:
MACRO A LOCAL READ1 PUSH DX MOV AH, 6 MOV DL, 0FFH CALL GetKey JE READ1 MOV A, AL POP DX
; közvetlenül a MACRO után!
; kód tárolása a kapott címen
ENDM
Struktúrák –C/C++ -szerű működés történik meg •Ez a –Struktúra definíciókat nem lehet egymásba ágyazni! •Csak elemi területfoglaló operátorok használhatók • strnév def-op: elemi területfoglaló operátor STRUC def-op kif mezőnév (DB,DW,DD,…) … mező kezdeti értéke kif: területfoglaláskor Strnév ENDS
Hívása név
strnév
< k.ért1,
lefoglalt terület neve; struktúra neve;
k.ért2, ... > mező kezdeti értékek
–Kezdeti értéket csak egyedi területfoglalási egységnek adhatunk át!
DB
1
DB 1,2 10 DUP ( ? ) DB ’SZOVEG’
; OK ; nem adható át kezdeti érték híváskor ; nem adható át kezdeti érték ; sztringnek kezdőérték adható!
–1 bájtos, 1 szavas, vagy 1 duplaszavas hossz –A mezők szomszédos bitek (1 vagy több) –Meghajtó programok írásakor nagyon hasznos!
•Portokra íráskor / portokról olvasáskor a bitcsoportoknak külön jelentésük van rekordnév
RECORD
mező:szélesség[=kif][,...]
–Ha nem adunk meg kezdőértéket, akkor nullázódik –A mezőnév konstanst jelent
•CL-be töltve és jobbra tolva kinyerhetjük a bitcsoport értékét –MASK operátor mezőnév előtt •A mezőhöz nem tartozó bitek törölhetők AND művelettel
Első menet
–Szimbólumtábla felépítése
•Utasítás-helyszámláló segítségével –Operációs kód tábla: minden mnemonikhoz a gépi kód bájtja(i), valamint az operandusok típusai •Címkék, változók, literálok, … offszetcímének feljegyzése •Makró definíciók feljegyzése Második menet –Tárgykód elkészítése •Szerkesztőnek szóló utasítások tárgykódba helyezése –Kimeneti fordítási listák készítése
Szerkesztő Fő feladatai
– Az azonos nevű és osztályú szegmens szeletek egymáshoz illesztése a szegmens szeletek definíciójában megadott módon, – a GROUP pszeudo utasítással egy csoportba sorolt szegmensek egymás után helyezése, – a relokáció elvégzése, – a külső hivatkozások (EXTRN) feloldása.
Lehetővé teszi a program akár különböző nyelveken készített részleteinek összeillesztését. Két menetes szerkesztés – Az első menetben táblázatokat készít • térkép (map) és globális szimbólum tábla – A második menetben a táblázatokban elhelyezett információk alapján elvégzi a szerkesztést.
Szerkesztési típusok Statikus szerkesztés –A tárgykódból közvetlenül a futtatható kódba kerül a gépi kód bájtfolyama – , hogy egyértelmű, milyen kódrészlet fog futni egy funkció hívásakor , hogy a gyakran, több programban is használt, nagyméretű kódrészletek mindegyikben – ismétlődnek Dinamikus szerkesztés –Ritkán használt, vagy több program által használt kódok futás közben, dinamikusan kerülnek betöltésre ( Pl. operációs rendszer szolgáltatásai is jellemzően ilyenek) , hogy csökken a programkód mérete – – , hogy a dinamikus könyvtárból akár több verziót is a rendszernek nyilván kell tartani és biztosítani a megfelelő elérhetőségét; lassabb lehet a futás a betöltési idő miatt; több fájlra bomlik a program
• • • • •
: szegmens kezdőcíme a memóriában : szegmens mérete
(0. helyiérték)
(1. helyiérték)
(2. helyiérték) (3. helyiérték) (4. helyiérték) (5-6. helyiérték) (7. helyiérték)
A lebegőpontos számok reprezentálására kezdetben társprocesszort, azaz egy FPU-t (Floating Point Unit) használtak. Ezt később integrálták a CPU-ba. Regiszterei –8 darab, 80 bites regiszter •ST(0), ST(1), …, ST(7)
•Körkörös verembe szervezve –Adat és utasítás mutatók; vezérlő regiszterek –Postfix jelölésmódú kiértékelés
MMX kiterjesztés (1997, Pentium) –8 darab új 64 bites regiszter (MM0, …, MM7 ) –Egész vagy lebegőpontos számműveletekhez •Hátrány: lebegőpontos műveletekhez és vissza üzemmódváltáskell (ami lassú) 1 utasítás, több adat – •Single nstriction ultiple ata •Pakolt számok (pl. 4 darab 16 bites szó a 64 biten elhelyezve) SSE kiterjesztés (1999, Pentium III) –128 bites regiszterek (XMM0, …, XMM7) –Egyszeres pontosságú lebegőpontos műveletek –Egész és lebegőpontos műveletek keveredhetnek –SSE, …, SSE4 változatok az évek folyamán
Általános célú regiszterek –64 bitesek •RAX, RBX, RCX, RDX, RBP, RSI, RDI, RSP •8 darab új regiszter: R8 –R15 –Név minden rövidített regisztermérethez •AL, BL, CL, DL, DIL, SIL, BPL, SPL, R8L, …, R15L –Alsó 8 bit •AX, BX, CX, DX, DI, SI, BP, SP, R8W, …, R15W –Alsó 16 bit •EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D, …, R15D –Alsó 32 bit
Utasításszámláló, FLAG –64 bitesek; RIP, RFLAGS Multimédia regiszterek –8 darab 64 bites egész vagy lebegőpontos műveletekhez (MMX/FPR) –16 darab 128 bites (XMM)
Címzés –Elméletileg 2 64 virtuális címtartomány –Manapság 48 bites a sín
•248maximálisan címezhető méret (256 terabájt!) Címzési mód –Szegmens regisztereken és deszkriptor táblákon keresztül, mint 32-bites esetben
Good Luck!