x86 Instructions

V seznamech v této části jsou pokyny označené hvězdičkou (*) zvlášť důležité. Pokyny, které nejsou tak označené, nejsou kritické.

Na procesoru x86 jsou instrukce proměnlivé velikosti, takže zpětné rozebírání je cvičení ve porovnávání vzorů. Chcete-li zpětně rozebrat adresu, měli byste začít rozebírat v okamžiku dalšího zpět, než opravdu chcete, a pak se podívejte dopředu, dokud pokyny začnou dávat smysl. Prvních pár instrukcí nemusí dávat smysl, protože jste možná začali rozebírat uprostřed instrukce. Existuje možnost, bohužel, že demontáž se nikdy nesynchronizuje s instrukčním proudem a budete se muset pokusit rozebrat v jiném počátečním bodě, dokud nenajdete výchozí bod, který funguje.

For well-packed switch statements, the compiler emits data directly into the code stream, so disassembling through a switch statement will usually stumble across instructions that make no sense (because they are really data). Najděte konec dat a pokračujte v rozebírání dat.

Zápis instrukcí

Obecným zápisem pro pokyny je umístit cílový registr vlevo a zdroj vpravo. Toto pravidlo ale může obsahovat několik výjimek.

Aritmetické instrukce jsou obvykle dvouregistrované ve zdrojovém a cílovém registru, které kombinují. Výsledek se uloží do cíle.

Některé pokyny mají 16bitovou i 32bitovou verzi, ale tady jsou uvedené jenom 32bitové verze. Tady nejsou uvedené pokyny s plovoucí desetinou čárkou, privilegované instrukce a instrukce, které se používají jenom v segmentovaných modelech (které Microsoft Win32 nepoužívá).

Pro úsporu místa se mnoho instrukcí vyjadřuje v kombinované podobě, jak je znázorněno v následujícím příkladu.

*

MOV

r1, r/m/#n

r1 = r/m/#n

znamená, že první parametr musí být registr, ale druhý může být registr, odkaz na paměť nebo okamžitá hodnota.

Chcete-li ušetřit ještě více místa, lze pokyny vyjádřit také, jak je znázorněno v následujícím příkladu.

*

MOV

r1/m, r/m/#n

r1/m = r/m/#n

to znamená, že první parametr může být registr nebo odkaz na paměť a druhý může být registr, odkaz na paměť nebo okamžitá hodnota.

Pokud není uvedeno jinak, nelze při použití této zkratky zvolit paměť pro zdroj i cíl.

Příponu bitové velikosti (8, 16, 32) navíc lze připojit ke zdroji nebo cíli, aby bylo možné určit, že parametr musí mít tuto velikost. R8 například znamená 8bitový registr.

Paměť, přenos dat a převod dat

Pokyny k přenosu paměti a dat nemají vliv na příznaky.

Platná adresa

*

LEA

r, m

Načtěte efektivní adresu.

(r = adresa m)

Například LEA eax, [esi+4] znamená eax = esi + 4. Tato instrukce se často používá k provádění aritmetik.

Přenos dat

MOV

r1/m, r2/m/#n

r1/m = r/m/#n

MOVSX

r1, r/m

Přesunutí s příponou znaménka

*

MOVZX

r1, r/m

Přesunutí s nulovým rozšířením

MOVSX and MOVZX are special versions of the mov instruction that perform sign extension or zero extension from the source to the destination. Toto je jediná instrukce, která umožňuje zdroji a cíli mít různé velikosti. (A ve skutečnosti musí být různé velikosti.

Manipulace se zásobníkem

The stack is pointed to by the esp register. The value at esp is the top of the stack (most recently pushed, first to be popped); older stack elements reside at higher addresses.

PUSH

r/m/#n

Nasdílení hodnoty do zásobníku

POP

r/m

Pop hodnota ze zásobníku

PUSHFD

Nasdílení příznaků do zásobníku

POPFD

Pop flags from stack.

PUSHAD

Odešle všechny celočíselné registry.

POPAD

Zobrazí všechna celočíselná registru.

ENTER

#n, #n

Sestavení rámce zásobníku

*

LEAVE

Roztrhání rámu zásobníku

The C/C++ compiler does not use the enter instruction. (The enter instruction is used to implement nested procedures in languages like Algol or Pascal.)

The leave instruction is equivalent to:

mov esp, ebp
pop ebp

Konverze dat

CBW

Convert byte (al) to word (ax).

CWD

Convert word (ax) to dword (dx:ax).

CWDE

Convert word (ax) to dword (eax).

CDQ

convert dword (eax) to qword (edx:eax).

Všechny převody provádějí rozšíření znaménka.

Aritmetická a bitová manipulace

Všechny aritmetické a bitové pokyny pro manipulaci upravují příznaky.

Aritmetika

ADD

r1/m, r2/m/#n

r1/m += r2/m/#n

ADC

r1/m, r2/m/#n

r1/m += r2/m/#n + carry

SUB

r1/m, r2/m/#n

r1/m -= r2/m/#n

SBB

r1/m, r2/m/#n

r1/m -= r2/m/#n + carry

NEG

r1/m

r1/m = -r1/m

INC

r/m

r/m += 1

DEC

r/m

r/m -= 1

CMP

r1/m, r2/m/#n

Compute r1/m - r2/m/#n

The cmp instruction computes the subtraction and sets flags according to the result, but throws the result away. It is typically followed by a conditional jump instruction that tests the result of the subtraction.

MUL

r/m8

ax = al * r/m8

MUL

r/m16

dx:ax = ax * r/m16

MUL

r/m32

edx:eax = eax * r/m32

IMUL

r/m8

ax = al * r/m8

IMUL

r/m16

dx:ax = ax * r/m16

IMUL

r/m32

edx:eax = eax * r/m32

IMUL

r1, r2/m

r1 *= r2/m

IMUL

r1, r2/m, #n

r1 = r2/m * #n

Násobení bez znaménka a znaménka Stav příznaků po násobení není definován.

DIV

r/m8

(ah, al) = (ax % r/m8, ax / r/m8)

DIV

r/m16

(dx, ax) = dx:ax / r/m16

DIV

r/m32

(edx, eax) = edx:eax / r/m32

IDIV

r/m8

(ah, al) = ax / r/m8

IDIV

r/m16

(dx, ax) = dx:ax / r/m16

IDIV

r/m32

(edx, eax) = edx:eax / r/m32

Nepodepsané a podepsané dělení. První registrace v pseudokódovém vysvětlení obdrží zbytek a druhý obdrží podíl. Pokud výsledek přeteče cíl, vygeneruje se výjimka přetečení dělení.

Stav příznaků po dělení není definován.

*

SETcc

r/m8

Set r/m8 to 0 or 1

If the condition cc is true, then the 8-bit value is set to 1. V opačném případě je 8bitová hodnota nastavená na nulu.

Binární kód desetinné číslo

Tyto pokyny se nezobrazí, pokud neladíte kód napsaný v COBOL.

DAA

Desetinná čárka se upraví po sčítání.

DAS

Desetinná čárka se upraví po odčítání.

These instructions adjust the al register after performing a packed binary-coded decimal operation.

AAA

Po přidání upravte sadu ASCII.

AAS

Nastavení ASCII po odčítání

These instructions adjust the al register after performing an unpacked binary-coded decimal operation.

AAM

ASCII se upraví po násobení.

AAD

ASCII se upraví po dělení.

These instructions adjust the al and ah registers after performing an unpacked binary-coded decimal operation.

Bity

AND

r1/m, r2/m/#n

r1/m = r1/m and r2/m/#n

OR

r1/m, r2/m/#n

r1/m = r1/m or r2/m/#n

XOR

r1/m, r2/m/#n

r1/m = r1/m xor r2/m/#n

NOT

r1/m

r1/m = bitwise not r1/m

*

TEST

r1/m, r2/m/#n

Compute r1/m and r2/m/#n

The test instruction computes the logical AND operator and sets flags according to the result, but throws the result away. Obvykle následuje podmíněný skok, který testuje výsledek logické funkce AND.

SHL

r1/m, cl/#n

r1/m <<= cl/#n

SHR

r1/m, cl/#n

r1/m >>= cl/#n zero-fill

*

SAR

r1/m, cl/#n

r1/m >>= cl/#n sign-fill

Poslední bit posunutý ven je umístěn v provedení.

SHLD

r1, r2/m, cl/#n

Posun doleva po dvou.

Shift r1 left by cl/#n, filling with the top bits of r2/m. Poslední bit posunutý ven je umístěn v provedení.

SHRD

r1, r2/m, cl/#n

Posunujte doprava dvakrát.

Shift r1 right by cl/#n, filling with the bottom bits of r2/m. Poslední bit posunutý ven je umístěn v provedení.

ROL

r1, cl/#n

Rotate r1 left by cl/#n.

ROR

r1, cl/#n

Rotate r1 right by cl/#n.

RCL

r1, cl/#n

Rotate r1/C left by cl/#n.

RCR

r1, cl/#n

Rotate r1/C right by cl/#n.

Otočení se podobá posunu, s tím rozdílem, že bity, které jsou posunuty ven, se znovu zobrazí jako příchozí bity výplně. Verze jazyka C pokynů pro otáčení zahrnuje přenosový bit do rotace.

BT

r1, r2/#n

Copy bit r2/#n of r1 into carry.

BTS

r1, r2/#n

Set bit r2/#n of r1, copy previous value into carry.

BTC

r1, r2/#n

Clear bit r2/#n of r1, copy previous value into carry.

Tok řízení

Jcc

dest

Branch conditional.

JMP

dest

Jump direct.

JMP

r/m

Jump indirect.

CALL

dest

Call direct.

*

CALL

r/m

Call indirect.

The call instruction pushes the return address onto the stack then jumps to the destination.

*

RET

#n

Vratka

The ret instruction pops and jumps to the return address on the stack. A nonzero #n in the RET instruction indicates that after popping the return address, the value #n should be added to the stack pointer.

LOOP

Decrement ecx and jump if result is nonzero.

LOOPZ

Decrement ecx and jump if result is nonzero and zr was set.

LOOPNZ

Decrement ecx and jump if result is nonzero and zr was clear.

JECXZ

Jump if ecx is zero.

Tyto instrukce jsou zbytky dědictví CISC x86 a v nedávných procesorech jsou ve skutečnosti pomalejší než ekvivalentní instrukce napsané dlouhou cestou.

Manipulace s řetězci

MOVST

Move T from esi to edi.

CMPST

Compare T from esi with edi.

SCAST

Scan T from edi for accT.

LODST

Load T from esi into accT.

STOST

Store T to edi from accT.

After performing the operation, the source and destination register are incremented or decremented by sizeof(T), according to the setting of the direction flag (up or down).

The instruction can be prefixed by REP to repeat the operation the number of times specified by the ecx register.

The rep mov instruction is used to copy blocks of memory.

The rep stos instruction is used to fill a block of memory with accT.

Vlajky

LAHF

Load ah from flags.

SAHF

Store ah to flags.

STC

Set carry.

CLC

Clear carry.

CMC

Complement carry.

STD

Set direction to down.

CLD

Set direction to up.

STI

Enable interrupts.

CLI

Disable interrupts.

Interlocked Instructions

XCHG

r1, r/m

Swap r1 and r/m.

XADD

r1, r/m

Add r1 to r/m, put original value in r1.

CMPXCHG

r1, r/m

Porovnání a výměna podmíněného nastavení

The cmpxchg instruction is the atomic version of the following:

   cmp     accT, r/m
   jz      match
   mov     accT, r/m
   jmp     done
match:
   mov     r/m, r1
done:

Rozmanitý

INT

#n

Přechádět na jádro.

BOUND

r, m

Trap if r not in range.

*

NOP

No operation.

XLATB

al = [ebx + al]

BSWAP

r

Pořadí bajtů prohození v registru

Here is a special case of the int instruction.

INT

3

Zarážka ladicího programu

The opcode for INT 3 is 0xCC. The opcode for NOP is 0x90.

Při ladění kódu možná budete muset opravit nějaký kód. Můžete to udělat tak, že nahradíte bajty, které budou 0x90.

Idiomy

XOR

r, r

r = 0

TEST

r, r

Check if r = 0.

*

ADD

r, r

Shift r left by 1.