Assembler alapjai

Amikor programot írsz össze az összeszerelőben, csak parancsokat írsz a processzorhoz. A processzor parancsai egyszerűen kódok vagy működési kódok vagy opcodes. Az opcodes valójában "olvasható szöveg" - hexadecimális kódok verziói. Emiatt az összeszerelőt a legalacsonyabb szintű programozási nyelvnek tekintik, az összeszerelőben levő mindent közvetlenül hexadecimális kódokká alakítanak át. Más szóval, nincs olyan fordítója, amely magas szintű nyelvet alakít alacsony szintű nyelvekké, az összeszerelő csak az összeszerelő kódokat konvertálja az adatokba.

Ebben a leckében több opcodes-t fogunk megvitatni, amelyek relevánsak a számításhoz, bit-műveletekhez stb. Más opcodes: ugrásparancsok, összehasonlítások, stb., Később kerülnek tárgyalásra.

Az összeszerelőben lévő számok bináris, tizedes vagy hexadecimális rendszerben ábrázolhatók. Annak érdekében, hogy megmutassa, melyik rendszert kell használni a számot kell fektetni után a betűk száma. A bináris rendszer van írva a levél b (például: 0000010b, 001011010b), akkor nem határozható meg semmit a tízes számrendszer szám után, vagy adja meg a levél d (például: 4589, 2356d), hexadecimális rendszerben meg kell adnia a levél h, hexadecimális számot meg kell írni, hogy a nulla az elején (példák: 00889h, 0AC45h, 056Fh, helytelenül F145Ch, S123h).

Az első csapat minden MOV-nek jól ismert. Ezzel a paranccsal másolhat (figyelmen kívül hagyhatja a parancsnév) értékeket egy helyről a másikra. Ez a "hely" lehet egy regiszter, egy memóriahely vagy egy azonnali érték (csak forrásértékként). Parancs szintaxisa:

Egy értéket másolhat egy regiszterből a másikba.

például: ez a parancs NEM megengedett:

Ez az opcode megpróbálja DWORD (32 bites) értéket bájtba helyezni (8 bit). Ezt nem teheti meg a mov paranccsal (ehhez más parancsok is vannak).

És ezek a parancsok helyesek, mert a forrás és a vevőegység nem különbözik méretétől:

Az értéket a memóriából is megkaphatja, és az egót beírhatja a regiszterbe. Vegyük például a következő memória sémát:

(Minden blokk egy byte-ot jelent)

Az offset értéket itt bájtként jelöljük, de valójában ez egy 32 bites érték. Vegyük a 3A példát, ez egy 32 bites érték is: 0000003Ah. Csak a helytakarékosság érdekében egyesek kisebb eltolásokat használnak.

Nézd meg a fenti táblázatban a 3A eltolását. Ezen eltérés adatai: 25, 7A, 5E, 72, EF, stb. Ha egy értéket a 3A offset-ből például egy regiszterbe kíván beadni, a mov parancsot is használhatja:

Eszközök: adjon meg egy értéket DWORD (32 bites) méretű memóriából, 3Ah eltolva az eax regiszterhez. A parancs végrehajtása után az eax tartalmazza a 725E7A25h értéket. Talán észrevetted, hogy ez egy inverzió a memóriából: 25 7A 5E 72. Ez azért van így, mert az értékeket a kis endian formátumban tárolják a memóriában. Ez azt jelenti, hogy a legkevésbé jelentős bájtot a legjelentősebb byte tárolja: a bájtok sorrendje az elejére. Úgy gondolom, hogy ezek a példák megmutatják ezt:

  • A dword (32 bites) érték 10203040 hexadecimális memóriában van tárolva: 40, 30, 20, 10
  • (16 bites) 4050 hexadecimális érték a memóriában tárolva: 50, 40

Térjünk vissza a fenti példához. Ezt más méretekkel is elvégezheti:

Valószínűleg már megértette, hogy a ptr előtag azt jelenti, hogy memóriából kell némi memóriát venni. És az előtag a ptr előtt jelöli az adatok méretét:

Néha a méret elhagyható:

Mivel EAX - 32-bites regiszter, a szerelő rájön, hogy ez is igényel egy 32 bites érték, ebben az esetben a memória offset 403045h.

Közvetlen értékekkel is rendelkezhet:

Ez a parancs egy írási a nyilvántartásban edx értéke 5006. A [és] zárójelek, használják, így az értéket a memóriából (a zárójelben ellensúlyozza), zárójel nélkül, ez csak egy közvetlen értéket.

A regiszter memóriahelyként is használható (32 bites 32 bites programokban):

A mov cx, [EAX], a processzor első néz ki, egy értéket (= memória cella) tartalmaz EAX, amelynek értéke, majd tárolja az ugyanezen memória cella, és tárolja ezt az értéket (szót, 16 bit, mivel a vevő, cx, a 16- bit regiszter) a CX-ben.

  • 1: tedd 100-at ecx-be
  • 2: tedd 200-at eax-ba
  • 3: Adja meg az értéket az ecx (= 100) a veremben (először helyezve)
  • 4: Helyezze el az értéket az eax (= 200) a veremről (legutoljára elhelyezett)
  • 5/6/7: ecx műveletek végrehajtása, az ecx változások értéke
  • 8: egy érték lekérése a stackből ebx: ebx lesz 200 (utolsó hely, első extrakció)
  • 9: az értékek lekérése a veremről az ecx-ban: az ecx ismét 100 lesz (első hely, utolsó kitermelés)

Ha meg szeretné tudni, hogy mi történik a memóriában, akkor az értékek elhelyezése és kibontása a veremben:

(a verem tele van nullákkal, de valójában nem ugyanaz, mint itt). Az ESP azon a helyen áll, amelyre pontosan utal)

Egy fontos megjegyzés: az eax regiszter szinte mindig az eljárás eredményének tárolására szolgál.

Ez a Windows funkciókra is vonatkozik. Természetesen bármilyen más regisztert is használhat a saját eljárásaiban, de ez normális.

Tehát a következő lecke véget ért. A következő leckében írjuk az első programot az assemblerben.

Körülbelül 0 a hexadecimális számok elején. Ez az, ami meg van írva ebben a témában, Zubkov ( „assembler DOS, Windows és Unix”, 1.2.3 hexadecimális.):


Az assembler programok felvételi kezdődő számok az A, B, C, D, E, F, az elején tulajdonított „0”, hogy megakadályozzák összetéveszthető számos változó neve, vagy más azonosítója. A hexadecimális számok után a "h"

Kapcsolódó cikkek