Condividi tramite


Istruzioni x86

Negli elenchi di questa sezione le istruzioni contrassegnate con un asterisco (*) sono particolarmente importanti. Le istruzioni non contrassegnate non sono critiche.

Nel processore x86 le istruzioni sono di dimensioni variabili, quindi il disassembling indietro è un esercizio nella corrispondenza dei modelli. Per smontare indietro da un indirizzo, è consigliabile iniziare a smontare a un punto più indietro di quello che si vuole veramente andare, quindi guardare avanti fino a quando le istruzioni iniziano a prendere senso. Le prime istruzioni potrebbero non avere senso perché potrebbe essere stato avviato il disassembling al centro di un'istruzione. C'è una possibilità, purtroppo, che il disassembly non si sincronizza mai con il flusso di istruzioni e sarà necessario provare a smontare in un punto di partenza diverso fino a trovare un punto di partenza che funziona.

Per istruzioni switch ben raggruppate, il compilatore genera dati direttamente nel flusso di codice, quindi il disassembling tramite un'istruzione switch in genere si scompone tra le istruzioni che non hanno senso (perché sono davvero dati). Trovare la fine dei dati e continuare a disassemblare lì.

Notazione istruzione

La notazione generale per le istruzioni consiste nell'inserire il registro di destinazione a sinistra e l'origine a destra. Tuttavia, possono essere presenti alcune eccezioni a questa regola.

Le istruzioni aritmetiche sono in genere due registri con i registri di origine e di destinazione che combinano. Il risultato viene archiviato nella destinazione.

Alcune delle istruzioni hanno sia versioni a 16 bit che a 32 bit, ma sono elencate qui solo le versioni a 32 bit. Non elencato qui sono istruzioni a virgola mobile, istruzioni con privilegi e istruzioni usate solo nei modelli segmentati (che Microsoft Win32 non usa).

Per risparmiare spazio, molte delle istruzioni vengono espresse in formato combinato, come illustrato nell'esempio seguente.

*

MOV

r1, r/m/#n

r1 = r/m/#n

significa che il primo parametro deve essere un registro, ma il secondo può essere un registro, un riferimento alla memoria o un valore immediato.

Per risparmiare ancora più spazio, le istruzioni possono essere espresse anche come illustrato di seguito.

*

MOV

r1/m, r/m/#n

r1/m = r/m/#n

ciò significa che il primo parametro può essere un registro o un riferimento alla memoria e il secondo può essere un registro, un riferimento alla memoria o un valore immediato.

Se non diversamente indicato, quando questa abbreviazione viene usata, non è possibile scegliere la memoria sia per l'origine che per la destinazione.

Inoltre, è possibile aggiungere un suffisso a dimensioni bit (8, 16, 32) all'origine o alla destinazione per indicare che il parametro deve essere di tale dimensione. Ad esempio, r8 indica un registro a 8 bit.

Memoria, trasferimento dati e conversione dati

Le istruzioni per il trasferimento dei dati e della memoria non influiscono sui flag.

Indirizzo effettivo

*

LEA

r, m

Caricare l'indirizzo effettivo.

(r = indirizzo di m)

Ad esempio, LEA eax, [esi+4] significa eax = esi + 4. Questa istruzione viene spesso usata per eseguire aritmetica.

Trasferimento dati

MOV

r1/m, r2/m/#n

r1/m = r/m/#n

MOVSX

r1, r/m

Spostare con estensione di firma.

*

MOVZX

r1, r/m

Spostarsi con estensione zero.

MOVSX e MOVZX sono versioni speciali dell'istruzione mov che eseguono l'estensione di firma o zero dall'origine alla destinazione. Questa è l'unica istruzione che consente all'origine e alla destinazione di essere dimensioni diverse. (E infatti, devono essere dimensioni diverse.

Manipolazione dello stack

Lo stack è indicato dal registro esp . Il valore in esp è la parte superiore dello stack (più di recente push, prima da visualizzare); gli elementi dello stack meno recenti risiedono in indirizzi superiori.

PUSH

r/m/#n

Eseguire il push del valore nello stack.

POP

r/m

Valore pop dallo stack.

PUSHFD

Eseguire il push dei flag nello stack.

POPFD

Flag pop dallo stack.

PUSHAD

Eseguire il push di tutti i registri interi.

POPAD

Pop all integer registers(Pop all integer registers).

INVIO

#n, #n

Frame dello stack di compilazione.

*

LASCIARE

Fotogramma dello stack di rimozione

Il compilatore C/C++ non usa l'istruzione invio . L'istruzione invio viene usata per implementare procedure annidate in lingue come Algol o Pascal.

L'istruzione di uscita equivale a:

mov esp, ebp
pop ebp

Conversione dei dati

CBW

Convertire byte (al) in word (ax).

CWD

Convertire la parola (ax) in dword (dx:ax).

CWDE

Convertire la parola (ax) in dword (eax).

CDQ

convertire dword (eax) in qword (edx:eax).

Tutte le conversioni eseguono l'estensione di firma.

Manipolazione aritmetica e bit

Tutte le istruzioni di manipolazione aritmetica e bit modificano i flag.

Aritmetica

ADD

r1/m, r2/m/#n

r1/m += r2/m/#n

ADC

r1/m, r2/m/#n

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

INV

r1/m, r2/m/#n

r1/m -= r2/m/#n

FFS

r1/m, r2/m/#n

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

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

Calcolo r1/m - r2/m/#n

L'istruzione cmp calcola la sottrazione e imposta i flag in base al risultato, ma genera il risultato. In genere è seguito da un'istruzione di salto condizionale che verifica il risultato della sottrazione.

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

Moltiplicazione senza segno e firmata. Lo stato dei flag dopo la moltiplicazione non è definito.

DIV

r/m8

(ah, al) = (axr/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

Divisione senza segno e firmato. Il primo registro nella spiegazione pseudocodice riceve il resto e il secondo riceve il quoziente. Se il risultato esegue il overflow della destinazione, viene generata un'eccezione di overflow di divisione.

Lo stato dei flag dopo la divisione non è definito.

*

SETcc

r/m8

Impostare r/m8 su 0 o 1

Se la condizione cc è true, il valore a 8 bit è impostato su 1. In caso contrario, il valore a 8 bit è impostato su zero.

Decimale codificato in codice binario

Queste istruzioni non verranno visualizzate a meno che non si stia eseguendo il debug del codice scritto in COBOL.

DAA

Regolazione decimale dopo l'aggiunta.

DAS

Regolazione decimale dopo la sottrazione.

Queste istruzioni regolano il registro al dopo aver eseguito un'operazione decimale con codice binario con pacchetto.

AAA

ASCII regola dopo l'aggiunta.

AAS

ASCII regola dopo la sottrazione.

Queste istruzioni regolano il registro al dopo aver eseguito un'operazione decimale con codice binario non compresso.

AAM

ASCII regola dopo la moltiplicazione.

AAD

ASCII regolare dopo la divisione.

Queste istruzioni regolano i registri al e ah dopo l'esecuzione di un'operazione decimale con codice binario non compresso.

Bit

AND

r1/m, r2/m/#n

r1/m = r1/m e r2/m/#n

OR

r1/m, r2/m/#n

r1/m = r1/m o r2/m/#n

XOR

r1/m, r2/m/#n

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

NOT

r1/m

r1/m = bit per bit non r1/m

*

TEST

r1/m, r2/m/#n

Calcolo r1/m e r2/m/#n

L'istruzione di test calcola l'operatore AND logico e imposta i flag in base al risultato, ma genera il risultato. In genere è seguito da un'istruzione di salto condizionale che verifica il risultato dell'and logico.

SHL

r1/m, cl/#n

r1/m <<= cl/#n

SHR

r1/m, cl/#n

r1/m >>= cl/#n riempimento zero

*

SAR

r1/m, cl/#n

r1/m >>= cl/#n riempimento dei segni

L'ultimo bit spostato fuori è posizionato nel trasporto.

SHLD

r1, r2/m, cl/#n

Maiusc a sinistra doppio.

Maiusc r1 lasciato da cl/#n, riempimento con i bit superiore di r2/m. L'ultimo bit spostato fuori è posizionato nel trasporto.

SHRD

r1, r2/m, cl/#n

Sposta a destra doppio.

Sposta r1 a destra per cl/#n, riempiendo con i bit inferiori di r2/m. L'ultimo bit spostato fuori è posizionato nel trasporto.

ROL

r1, cl/#n

Ruotare r1 a sinistra da cl/#n.

ROR

r1, cl/#n

Ruotare r1 a destra per cl/#n.

RCL

r1, cl/#n

Ruotare r1/C a sinistra per cl/#n.

RCR

r1, cl/#n

Ruotare r1/C a destra per cl/#n.

La rotazione è simile allo spostamento, ad eccezione del fatto che i bit spostati vengono visualizzati nuovamente come bit di riempimento in ingresso. La versione in linguaggio C delle istruzioni di rotazione incorpora il bit di trasporto nella rotazione.

BT

r1, r2/#n

Copiare bit r2/#n di r1 nel trasporto.

BTS

r1, r2/#n

Impostare bit r2/#n di r1, copiare il valore precedente nel trasporto.

BTC

r1, r2/#n

Cancella bit r2/#n di r1, copiare il valore precedente nel trasporto.

Flusso di controllo

Jcc

Dest

Condizionale ramo.

JMP

Dest

Saltare direttamente.

JMP

r/m

Saltare indiretto.

CALL

Dest

Chiamare direttamente.

*

CALL

r/m

Chiamare indiretto.

L'istruzione di chiamata esegue il push dell'indirizzo restituito nello stack e quindi passa alla destinazione.

*

RET

#n

Return

L'istruzione ret viene visualizzata e passa all'indirizzo restituito nello stack. Un #n diverso da zero nell'istruzione RET indica che dopo aver visualizzato l'indirizzo restituito, il valore #n deve essere aggiunto al puntatore dello stack.

CICLO

Decrement ecx e jump se il risultato è diverso da zero.

LOOPZ

Decrement ecx e jump se il risultato è diverso da zero e zr è stato impostato.

LOOPNZ

Decrement ecx e jump se il risultato è diverso da zero e zr era chiaro.

JECXZ

Saltare se ecx è zero.

Queste istruzioni sono resti dell'eredità CISC di x86 e nei processori recenti sono effettivamente più lente rispetto alle istruzioni equivalenti scritte per lungo tempo.

Manipolazione delle stringhe

MOVST

Sposta T da esi a edi.

CMPST

Confrontare T da esi con edi.

SCAST

Analizzare T da edi per accT.

LODS T

Caricare T da esi in accT.

STOST

Archiviare T a edi da accT.

Dopo aver eseguito l'operazione, il registro di origine e destinazione viene incrementato o decrementato da sizeof(T), in base all'impostazione del flag di direzione (su o giù).

L'istruzione può essere preceduta da REP per ripetere l'operazione il numero di volte specificato dal registro ecx .

L'istruzione rep mov viene usata per copiare blocchi di memoria.

L'istruzione rep stos viene usata per riempire un blocco di memoria con accT.

Bandiere

LAHF

Caricare ah dai flag.

SAHF

Archiviare ah per contrassegnare.

STC

Impostare il trasporto.

CLC

Porta libera.

CMC

Complemento porta.

STD

Impostare la direzione verso il basso.

CLD

Impostare la direzione verso l'alto.

STI

Abilitare gli interrupt.

CLI

Disabilitare gli interrupt.

Istruzioni interlocked

XCHG

r1, r/m

Scambia r1 e r/m.

XADD

r1, r/m

Aggiungere r1 a r/m, inserire il valore originale in r1.

CMPXCHG

r1, r/m

Confronto e scambio condizionale.

L'istruzione cmpxchg è la versione atomica del seguente:

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

Varie

INT

#n

Trap per il kernel.

ASSOCIATO

r, m

Trap se r non è compreso nell'intervallo.

*

NOP

Nessuna operazione.

XLATB

al = [ebx + al]

BSWAP

r

Scambia l'ordine dei byte nel registro.

Ecco un caso speciale dell'istruzione int .

INT

3

Trap del punto di interruzione del debugger.

Il codice operativo per INT 3 è 0xCC. Il codice operativo per NOP è 0x90.

Quando si esegue il debug del codice, potrebbe essere necessario applicare patch ad alcuni codice. A tale scopo, sostituire i byte che causano l'offesa con 0x90.

Idiomi

XOR

r, r

r = 0

TEST

r, r

Controllare se r = 0.

*

ADD

r, r

Maiusc r a sinistra di 1.