Utasítások

From WIKi

Jump to: navigation, search

A feladatsor tele van hibákkal, használata nem ajánlott.

Első csoport . . . Utasítások . . . Eljárások . . . Megírandó programok . . . Mit ír ki a program??


Tartalomjegyzék

Mire szolgál és hogyan működik az XLAT utasítás?

Egy byte lefordítása egy másik bytra egy max 255 byte hosszú úgynevezett fordítási táblázat alapján. A táblázat kezdőcíme EBX-ben van (vagy BX-ben, ha egy 16 bites kódban helyezkedik el az utasítás), és AL tartalmát felülírja a táblázat AL edik elemével ( ~MOV([EBX+AL],AL))

Hogyan férhetünk hozzá a flag regiszer tartalmához?

A LAHF (Load AH from Flag) utasítással a AH regiszterbe töltődik a FLAG regiszter alsó bájtja, vagy PUSHF ill. PUSFD utasítással a teljes FLAG ill. EFlag a verembe kerül és onnan kiolvashatjuk.

Mely utasítások írnak a verembe?

A PUSH utasítás különböző változatainak az a fő tevékenysége, hogy a verembe írjon valamit. Ezek: PUSH, PUSHW, PUSHD, PUSHA, PUSHAD, PUSHF, PUSHFD

Ezen túlmenően írnak még a verembe azok az utasítások is, melyek ideiglenesen félbeszakítják egy programkód működését. Ilyen a szubrutinhívás (CALL) és a megszakítás (INT) esete. Ezen utasítások az EIP (ill. IP) regiszter tartalmát helyezik el a veremben annak érdekében, hogy az ideiglenes tevékenység befejezése után a program ugyanott folytatódhasson, ahol azt félbeszakítottuk. (Az INT utasítás a visszatérési címen kívül verembe helyezi még a Flag regiszter tartalmát (F vagy EF), és a CS szegmensregisztert is. Ez utóbbit (CS) az ú.n. távoli eljárások meghívása során a CALL utasítás is kiírja a verembe.)

Mely utasítások olvasnak a veremből?

A POP utasítás különböző változatainak az a fő tevékenysége, hogy a adatot vegyenek ki a veremből. Ezek: POP, POPW, POPD, POPA, POPAD, POPF, POPFD.

Ezen túlmenően a veremből olvassák ki a program folytatásához szükséges információt (IP vagy EIP ill. CS és F vagy EF) a szubrutinból való visszatérésnél a RET utasítás, továbbá a megszakításokból történő visszatérésnél az IRET utasítás.

A FLAG regiszter mely bitjeit tudjuk közvetlenül, egyetlen utasítással módosítani?

Ezek a bitek a

  • CF – carry
  • DF – direction
  • FI – interrupt enable

Mindegyiküket lehet 0-ra (CLear) vagy 1-re (Set) állítani, illetve a carry flaget lehet negálni (CoMplement) is.

A Flageket közvetlenül módosító utasítások:
CLC, STC, CMC, CLD, STD, CLI, STI

Milyen módozatai vannak a feltétel nélküli JMP utasításnak?

  • Direct ugrások (tipikusan egy cimke segítségével adjuk meg az ugrás célpontját) Az utasítás és a cél közötti viszonytó függően az alábbi esetek lehetségesek:
    1. jmp disp8
      Előjeles bájt távolságon belüli (-128 .. +127) ugrás. Az ilyen ugrás gépi kódja a legrövidebb, hiszen csak 1 bájtnyi információt kell elhelyezni benne az ugrás célpontjára vonatkozóan.
    2. jmp disp32 ; vagy 16 bites kódban: jmp disp16
      szegmensen belüli ugrás
    3. jmp adrs48 ; vagy 16 bites kódban: jmp adrs32
      közvetlen, szegmensen kívüli, szegmens+offset cím, szegmens mindig 16 bitet igényel, az offszet viszont a kód-mérettől függően 16 vagy 32 bites lehet.
      (Windows és LINUX alatt inkább csak elvi jelentőségű lehetőség. Ezek az operációs rendszerek nem bontják szegmensekra a memóriát, így nem tudunk az ezen rendszerek alatt működő programokban távoli címeket deklarálni.)
  • Indirect ugrások. Az operandus nem magát az ugrás célpontját határozza meg, hanem arról ad információt, honnan kell kiolvasni a címet.
    • 16 bites kódban:
      1. jmp reg16
        regiszter-közvetett, szegmensen belüli. A regiszterből lesz kiolvasva a az IP regiszer új értéke (az ugrás célpontja).
      2. jmp mem16
        közvetett, szegmensen belüli vagy másképpen közeli ugrás, A megadott memóricímről lesz kiolvasva a az IP regiszer új értéke (az ugrás célpontja).
      3. jmp mem32
        közvetett, szegmensen kívüli, A megadott memóriacímről lesz kiolvasva a az IP és a CS regiszerek új értéke (az ugrás célpontja).
    • 32 bites kódban (Windows, Linux):
      1. jmp reg32
        regiszter-közvetett, szegmensen belüli. A regiszterből lesz kiolvasva a az EIP regiszer új értéke (az ugrás célpontja).
      2. jmp mem32
        közvetett, szegmensen belüli vagy másképpen közeli ugrás, A megadott memóricímről lesz kiolvasva a az EIP regiszer új értéke (az ugrás célpontja).
      3. jmp mem48
        közvetett, szegmensen kívüli, A megadott memóriacímről lesz kiolvasva a az EIP és a CS regiszerek új értéke (az ugrás célpontja). (itt is érvényes a fentebbi megjegyzés, ezt az elvi lehetőséget aligha fogjuk kihasználni.)

Mely feltételes ugrásokat használhatjuk előjeles mennyiségek összehasonlítása után

Az összehasonlításra használt CMP(cél,forrás) utasítás a cél-forrás kivonásnak megfelelően állítja az állapotjelzőket. Az összehasonlítást követő feltételes ugró utasítások ezeket az állapotjelzőket vizsgálják meg. Ha a CMP utasítás operandusai előjeles egészek voltak, akkor a számol lözötti hagyományos relációkat az alábbi feltételes ugrásokkal vizsgálhatjuk:

  • JG cimke
    ugrik, ha cél>forrás (OF==SF és ZF==0)
  • JL cimke
    ugrik, ha cél<forrás (OF!=SF)
  • JE cimke
    ugrik, ha cél==forrás (ZF==1)
  • JGE cimke
    ugrik, ha cél>=forrás (OF==SF)
  • JLE cimke
    ugrik, ha cél<=forrás (OF!=SF vagy ZF==1)
  • JNE cimke
    ugrik, ha cél!=forrás (ZF==0)
  • JNG cimke
    ugyanaz, mint JLE cimke
  • JNL cimke
    ugyanaz, mint JGE cimke
  • JNGE cimke
    ugyanaz, mint JL cimke
  • JNLE cimke
    ugyanaz, mint J cimke

Az utasítások mnemonikjában a különböző betűk az alábbi angol szavakra utalnak:

  • G Greater ~ nagyobb
  • L Less ~ kisebb
  • E Equal ~ egyenlő
  • N Not ~ nem

Az ugrás helyének egy előjeles bájtnyi távolságon belül (-128 .. +127) kell lennie.

Mely felt. ugrásokat használhatjuk előjel nélküli mennyiségek összehasonlítása után

Az összehasonlításra használt CMP(cél,forrás) utasítás a cél-forrás kivonásnak megfelelően állítja az állapotjelzőket. Az összehasonlítást követő feltételes ugró utasítások ezeket az állapotjelzőket vizsgálják meg. Ha a CMP utasítás operandusai előjel nélküli természetes számok voltak, akkor a számol lözötti hagyományos relációkat az alábbi feltételes ugrásokkal vizsgálhatjuk:

  • JA cimke
    ugrik, ha cél>forrás (CF==0 és ZF==0)
  • JB cimke
    ugrik, ha cél<forrás (CF==1)
  • JE cimke
    ugrik, ha cél==forrás (ZF==1)
  • JAE cimke
    ugrik, ha cél>=forrás (CF==0)
  • JBE cimke
    ugrik, ha cél<=forrás (CF==1 vagy ZF==1)
  • JNE cimke
    ugrik, ha cél!=forrás (ZF==0)
  • JNA cimke
    ugyanaz, mint JBE cimke
  • JNB cimke
    ugyanaz, mint JAE cimke
  • JNAE cimke
    ugyanaz, mint JB cimke
  • JNBE cimke
    ugyanaz, mint JA cimke

Az utasítások mnemonikjában a különböző betűk az alábbi angol szavakra utalnak:

  • A Above ~ fölötte/nagyobb
  • B Below ~ alatta/kisebb
  • E Equal ~ egyenlő
  • N Not ~ nem

Az ugrás helyének egy előjeles bájtnyi távolságon belül (-128 .. +127) kell lennie.

Mely ugró utasítások vizsgálják közvetlenül az egyes állapotjelzőket?

  • JC cimke
    ugrik, ha CF==1
  • JNC cimke
    ugrik, ha CF==0
  • JP cimke
    ugrik, ha PF==1
  • JPE cimke
    ugrik, ha páros (Even); ugyanaz, mint JP cimke
  • JNP cimke
    ugrik, ha PF==0
  • JPO cimke
    ugrik, ha páratlan (Odd); ugyanaz, mint JNP cimke
  • JZ cimke
    ugrik, ha ZF==1
  • JNZ cimke
    ugrik, ha ZF==0
  • JS cimke
    ugrik, ha SF==1
  • JNS cimke
    ugrik, ha SF==0
  • JO cimke
    ugrik, ha OF==1
  • JNO cimke
    ugrik, ha OF==0

Az ugrás helyének egy előjeles bájtnyi távolságon belül (-128 .. +127) kell lennie.

Ismertesse a CALL és RET utasításokat!

CALL – szubrutin hívása

  • közeli hívás: EIP értéke a verembe kerül, majd felülíródik a szubrutin címével
  • távoli hívás: CS és EIP értéke a verembe kerül, majd felülíródnak a szubrutin szegmens és offset címével. (Windows, Linux alatt gyakorlatilag nem használunk távoli eljárásokat.)

Az eljárás meg lehet adva

  • direkt
    • CALL eljárás_név
      ill.
    • CALL közeli_cím
    • CALL távoli_cím
  • vagy indirekt módon
    • CALL(reg32)
    • CALL(mem32)
      esetleg távoli eljárás esetén
    • CALL(mem48)

RET [(num_kif)] – szubrutinból való visszatérés a hívást követő utasításra

  • visszatérés közeli hívásból: EIP értéke felülíródik a veremből
  • visszatérés távoli hívásból: EIP majd CS értéke felülíródik a veremből
  • Ha szerepel (num_kif), akkor megnöveli a veremmutató értékét, és ezzel eltünteti a veremből az eljárás argumentumait (~ ADD(num_kif,ESP)).

Ismertesse az INT és IRET utasításokat

  • INT(bájt_konstans);
  • INT;// Majdnem ugyanaz, mint: INT(3);
  • INTO;// Majdnem ugyanaz, mint: IF(@O) THEN INT(4) ENDIF;

Az INT utasítás (és változatai) segítségével a programkódból lehet aktiváni a megszakítás kezelő rutinokat. Attól eltekintve, hogy ezen esetekben a programozó akarata indítja el a folyamatot, míg a külső megszakításoknál egy a külvilágból érkező jel, a két művelet azonos módon zajlik le. Mivel a megszakítás kezelők mindig csak ideiglenesen szakítják meg a program működését, biztosítani kell annak lehetőségét, hogy a későbbiek során a program úgy folytatódhasson, mintha nem is történt volna megszakítás. A probléma mentes visszatérés érdekében a megszakításnak el kell mentenie legalább a soron következő utasítás pontos címét. A 80x86-os processzorcsalád ezen túlmenően menti még a Flag regiszter tartalmát is. (Védett módban még további információkat is elment.)

INT(konst);
//PUSHF;CLT;IF(külső_megsz.) then CLI endif; PUSH(CS);PUSH(IP);
//CLT ~ törli a trap flaget; (Valójában nincs ilyen urasítás.)

  • FONTOS: (Ha megszakítás kezelőt szeretnénk írni.) A flageken és az utasítás mutatón kívül minden mást a megszakítás kezelő rutinnak kell elmentenie (és helyreállítania), ha használni szeretné. Ezért az ilyen rutinok gyakran kezdődnek egy PUSHA utasítással.

Az operandus nélküli INT utasítás a nyomkövetés segítését szolgálja. Annyiban különbözik az "INT(3)" utasítástól, hogy mindössze egyetlen bájtot foglal el a gépi kódja. Ezzel segítik, hogy a nyomkövető programok egyszerűen tudjanak töréspontot elhelyezni a programban.

A 0-s sorszámú megszakítás az osztási hibához tartózó eltérülés kezelője.
Az 1-es sorszámút a Trap flag 1 értéke aktiválja minden egyes utasítást követően.
A 2-es az ú.n. nem maskolható külső megszakításhoz (NMI) tartozik.
A 4-es számú megszakítás az INTO utasításhoz kötődik. Amennyiben az utasítás végrehajtása idején az overflow flag értéke 1, akkor kerül meghívásra ez a megszakítás kezelő. Ha OF értéke nulla, akkor a progarm egyszerűen folytatódik az INTO utáni utasítás végrehajtásával.

Némelyik operációs rendszer is formális megszakításokon keresztül nyújt elérési lehetőséget a szolgáltatásai fele.

  • DOS alatt pl. nevezetes a $21-es megszakítás, melyet DOS funkció hívásnak neveznek.
  • Linux alatt az INT($80) uatasítással érhetjük el az operációs rendszer szolgáltatásait, pl. a program befejezésének kérését.
  • A Windows más utat választott erre a célra. Ezért Windows alatt kerüljük az INT utasítás használatát.


IRET;
Ez az utasítás a megszakítás kezelőből történő visszatérést szolgálja. Lényegében kiolvassa a veremből mindazon információkat, melyeket a megszakítás hívás helyezett el. Utolsó lépésben helyreállítja az utasítás mutató (EIP) értékét, és ezzel megtaremti a lehetőséget, hogy a program működése ott folytatódjon, ahol a megszakítás miatt félbeszakadt.

Ismertesse az aritmetnikai utasításokat!

Összeadás, kivonás

  • ADD (forrás,cél);// cél=cél+forrás 8,16,32 bit
  • ADC (forrás,cél);// cél=cél+forrás+CF (Segítségével a processzor által közvetlenül nem támogatott, nagyméretű -sok biten tárolt- számok összeadása is megoldható.)
  • SUB (forrás,cél);// cél=cél-forrás
  • SBB (forrás,cél);// cél=cél-forrás-CF (Segítségével a processzor által közvetlenül nem támogatott, nagyméretű -sok biten tárolt- számok kivonása is megoldható.)
  • NEG (cél);// cél=0-cél

Fenti utasítások az összes állapotjelzőt (CF, PF, AF, ZF, SF és OF) értelemszerűen állítják.

  • INC (cél);// ~ADD(1,cél)
  • DEC (cél);// ~SUB(1,cél)

Fenti két utasítás -az eltérő gépi kódon kívül- annyiban más, mint a megfelelő összeadó/kivonó utasítás, hogy változatlanul hagyják a CF bitet. A többi állapotjelzőt viszont ugyanúgy módosítják, mint a helyettesítő kód.

  • CMP(cél,forrás);// ~MOV(cél,TMP);SUB(forrás,TMP); (Annyiban tér el a SUB(forrás, cél) utasítástól, hogy nem tárolja a kivonás eredményét, csak az állapotjelzőket módosítja.

Szorzás

  • INTMUL(forrás,cél);// cél=cél*forás
  • INTMUL(konstans,forrás,cél);// cél=konstans*forrás (Itt a forrás csak memória operandus, vagy regiszter lehet.)

Fenti két utasításnál

    • a céloperandus csak 16 vagy 32 bites általános célú regiszter lehet.
    • a szorzandók előjeles egészként lesznek értelmezve
  • MUL(szorzó);// szorzó méretétől függően:
    • AX=AL*szorzó
    • (DX:AX)=AX*szorzó
    • (EDX:EAX)=EAX*szorzó

A MUL utasításnál a szorzandók előjel nélküli (természetes) számok.

  • IMUL(szorzó);// Hasonlóan működik, mint a MUL utasítás, csak előjeles számként értelmezi a szorzandókat.

A szorzó utasítások határozatlan értéket helyeznek el a PF, AF, ZF és SF jelzőbitekben. CF=OF pedig azt jelzi, hogy az eredménynek a szorzandókkal megegyező számú alacsony helyiértékű bitje a helyes eredményt tartalmazza-e: (0-igen, 1-nem).

Osztás

  • DIV(osztó);// Az osztó méretétől függően:
    • AX/osztó==>AL                    ill.      AX%osztó==>AH
    • (DX:AX)/osztó==>AX           ill.       (DX:AX)%osztó==>DX
    • (EDX:EAX)/osztó==>EAX     ill.      (EDX:EAX)%osztó==>EDX

A DIV utasításnál az osztandó és az osztó előjel nélküli (természetes) számok.

  • IDIV(osztó);// Hasonlóan működik, mint a DIV utasítás, csak előjeles számként értelmezi az osztandót és az osztót.

Az osztások minden állapotjelzőt határozatlan értékre módosítanak.

Amennyiben a hányados nem ábrázplható az osztónak megfelelő méretű regiszterben, akkor az utasítás aktiválja a 0 sorszámú kivételt.

Ismertesse a veremkezelő utasításokat!

  • PUSH(forrás); //forrás:16/32bit mem/reg
  • PUSHW(forrás); //forrás:16bit mem/reg/konstans
  • PUSHD(forrás); //forrás:32bit mem/reg/konstans
  • POP(cél); //cél:16/32bit mem/reg
  • POPW(cél); //cél:16bit mem/reg
  • POPD(cél); //cél:32bit mem/reg
  • PUSHA; // PUSH([AX-DX,SP,BP,SI,DI])
  • POPA; // PUSH([AX-DX,SP,BP,SI,DI])visszafele
  • PUSHAD,POPAD 32 bites reg
  • PUSHF //FLAG a verembe; POPF //a veremből

A verem teteje pozíciót a memóriábam az ESP regiszter jelöli ki.

A PUSH utasítás előbb csökkenti a veremmutató (ESP) értékét az operandus méretének megfelelően, majd az új verem teteje címre kimásolja az utasítás operandusát.

A POP utasítás -pont fordított sorrendben- előbb kimásolja a verem teteje címen található adatot az operandusba, majd növeli a veremmutató (ESP) értékét az operandus méretének megfelelően.

Bár elvileg 16 és 32 bites operandusokkal is működnek ezek az utasítások, törekedjünk arra, hogy mindig 32 bites mennyiségeket helyezzünk el a veremben.

Ismertesse a logikai utasításokat!

  • NOT(cél);// cél bitenkénti complementálása
  • AND(forrás,cél);// bitenkénti és művelet
  • OR(forrás,cél);// bitenkénti vagy művelet
  • XOR(forrás,cél);// bitenkénti kizáró vagy művelet
  • TEST(forrás,cél);// bitenkénti és művelet, az eredmény tárolása nélkül (a többi utasításnál a cél operandus tartalmazza az eredményt)

A NOT utasítás nem változtatja meg az állapotjelzőket.

A többi utasítást követően értelemszerű információt olvashatunk ki a PF, ZF és SF jelzőbitekből.

Ismertesse a forgató utasításokat!

  • ROR(számláló,cél);
  • ROL(számláló,cél);

Ezen utasítások jobbra (ROR) ill. balra (ROL) forgatják az operandusban lévő biteket. A szélen kilépő bit egyrészről beforog az operandus másik végén, másrészről pedig kimásolódik a CF jelzőbitbe. A számláló (vagy egy konstans, vagy a CL regiszter) határozza meg, hogy mennyivel mozdul el egy-egy bit az eredeti helyéhez képest.

  • RCR(számláló,cél);
  • RCL(számláló,cél);

Ezen utasítások annyiban térnek el az egyszerű forgatásoktól, hogy a CF-el kiegészített cél operandust forgatják el, azaz a CF eredeti tartalma bekerül a cél operandusba.

A forgató utasítások a CF mellett még az OF értékét változtatják meg:

  • számláló==0 esetén nem (mégsem) változik meg az OF tartalma
  • számláló==1 esetén
    • OF=1, ha a forgatás hatására megváltozik a céloperandus legmagasabb helyiértékű bitje (azaz az előjele), és
    • OF=0, ha a legmagasabb helyiértékű bit nem változik meg
  • számláló>1 esetén OF határozatlan értékre változik

Ismertesse a léptető utasításokat!

  • SHL(számláló,cél);
  • SHR(számláló,cél);

A számláló (vagy egy konstans, vagy a CL regiszter) által meghatározott számú bittel eltolja a cél operandus bitjeit balra (SHL) ill. jobbra (SHR). Az utoljára kilépő bitet a CF-be helyezi. A másik oldalon 0 bitek lépnek be az operandusba.

A balra tolás megfelel a 2 hatványaival történő szorzásnak, míg a jobbra tolás az előjel nélküli számok 2 hatványaival történő osztásának feleltethető meg.

  • SAL(számláló,cél);// Csak a nevében különbözik az SHL utasítástól, egyébként teljesen ugyanúgy működik (mivel azonos a gépi kódja is).
  • SAR(számláló,cél);// Arithmetikai azaz az előjel megőrzésével történő eltolás. A magas helyiértékre nem automatikus 0-k lépnek be, mint az SHR utasításnál, hanem az eredetileg ott lévő érték marad az új érték is. Ez az utasítás az előjeles számok 2 ahtványaival történő osztásával hozható kapcsolatba. (Ha az osztás nem egész eredményt ad, akkor az SAR mindig a -végtelen felé kerekít.


Az eltoló utasítások az OF értékét is megváltoztatják:

  • számláló==0 esetén nem (mégsem) változik meg az OF tartalma
  • számláló==1 esetén
    • OF=1, ha az eltolás hatására megváltozik a céloperandus legmagasabb helyiértékű bitje (azaz az előjele), és
    • OF=0, ha a legmagasabb helyiértékű bit nem változik meg
  • számláló>1 esetén OF határozatlan értékre változik

Értelemszerű információt olvashatunk ki a PF. ZF és SF jelzőbitekből is.



Első csoport . . . Utasítások . . . Eljárások . . . Megírandó programok . . . Mit ír ki a program??

A feladatsor tele van hibákkal, használata nem ajánlott.

Personal tools