Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Nas listas desta seção, as instruções marcadas com um asterisco (*) são particularmente importantes. As instruções não tão marcadas não são críticas.
No processador x86, as instruções são de tamanho variável, portanto, desmontar para trás é um exercício de correspondência de padrões. Para desmontar para trás de um endereço, você deve começar a desmontar em um ponto mais atrás do que realmente deseja ir e, em seguida, olhar para frente até que as instruções comecem a fazer sentido. As primeiras instruções podem não fazer nenhum sentido porque você pode ter começado a desmontar no meio de uma instrução. Há uma possibilidade, infelizmente, de que a desmontagem nunca seja sincronizada com o fluxo de instrução e você terá que tentar desmontar em um ponto de partida diferente até encontrar um ponto de partida que funcione.
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). Localize o final dos dados e continue desmontando lá.
Notação de instrução
A notação geral para instruções é colocar o registro de destino à esquerda e a origem à direita. No entanto, pode haver algumas exceções a essa regra.
Normalmente, as instruções aritméticas são dois registros com os registros de origem e de destino combinados. O resultado é armazenado no destino.
Algumas das instruções têm versões de 16 e 32 bits, mas apenas as versões de 32 bits estão listadas aqui. Não listados aqui estão instruções de ponto flutuante, instruções privilegiadas e instruções que são usadas apenas em modelos segmentados (que o Microsoft Win32 não usa).
Para economizar espaço, muitas das instruções são expressas em forma combinada, conforme mostrado no exemplo a seguir.
* |
MOV |
r1, r/m/#n |
r1 = r/m/#n |
significa que o primeiro parâmetro deve ser um registro, mas o segundo pode ser um registro, uma referência de memória ou um valor imediato.
Para economizar ainda mais espaço, as instruções também podem ser expressas, conforme mostrado a seguir.
* |
MOV |
r1/m, r/m/#n |
r1/m = r/m/#n |
o que significa que o primeiro parâmetro pode ser um registro ou uma referência de memória, e o segundo pode ser um registro, uma referência de memória ou um valor imediato.
A menos que observado de outra forma, quando essa abreviação for usada, você não poderá escolher memória para origem e destino.
Além disso, um sufixo de tamanho de bit (8, 16, 32) pode ser acrescentado à origem ou ao destino para indicar que o parâmetro deve ser desse tamanho. Por exemplo, r8 significa um registro de 8 bits.
Memória, Transferência de Dados e Conversão de Dados
As instruções de memória e transferência de dados não afetam sinalizadores.
Endereço efetivo
* |
LEA |
r, m |
Carregar endereço efetivo. (r = endereço de m) |
Por exemplo, LEA eax, [esi+4] significa eax = esi + 4. Essa instrução geralmente é usada para executar aritmética.
Transferência de dados
MOV |
r1/m, r2/m/#n |
r1/m = r/m/#n |
|
MOVSX |
r1, r/m |
Mova-se com a extensão de sinal. |
|
* |
MOVZX |
r1, r/m |
Mova-se com extensão zero. |
MOVSX and MOVZX are special versions of the mov instruction that perform sign extension or zero extension from the source to the destination. Esta é a única instrução que permite que a origem e o destino sejam tamanhos diferentes. (E, na verdade, eles devem ter tamanhos diferentes.
Manipulação de pilha
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 |
Efetuar push do valor para a pilha. |
|
POP |
r/m |
Valor pop da pilha. |
|
PUSHFD |
Efetuar push de sinalizadores na pilha. |
||
POPFD |
Pop flags da pilha. |
||
PUSHAD |
Envie por push todos os registros inteiros. |
||
POPAD |
Pop de todos os registros inteiros. |
||
ENTER |
#n, #n |
Criar quadro de pilha. |
|
* |
LEAVE |
Dividir o quadro de pilha |
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
Conversão de dados
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). |
Todas as conversões executam a extensão de sinal.
Manipulação aritmética e de bits
Todas as instruções aritméticas e de manipulação de bits modificam sinalizadores.
Aritmética
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 |
Multiplicação sem sinal e assinada. O estado dos sinalizadores após a multiplicação é indefinido.
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 |
Divisão não assinada e assinada. O primeiro registro na explicação pseudocódigo recebe o restante e o segundo recebe o quociente. Se o resultado estourar o destino, uma exceção de estouro de divisão será gerada.
O estado dos sinalizadores após a divisão é indefinido.
* |
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. Caso contrário, o valor de 8 bits será definido como zero.
Decimal codificado em binário
Você não verá essas instruções, a menos que esteja depurando o código escrito em COBOL.
DAA |
Ajuste decimal após a adição. |
|
DAS |
Ajuste decimal após a subtração. |
These instructions adjust the al register after performing a packed binary-coded decimal operation.
AAA |
Ajuste ASCII após a adição. |
AAS |
ASCII ajuste após a subtração. |
These instructions adjust the al register after performing an unpacked binary-coded decimal operation.
AAM |
Ajuste ASCII após a multiplicação. |
AAD |
ASCII ajuste após a divisão. |
These instructions adjust the al and ah registers after performing an unpacked binary-coded decimal operation.
Bits
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. Normalmente, ele é seguido por uma instrução de salto condicional que testa o resultado do AND lógico.
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 |
O último bit deslocado é colocado no transporte.
SHLD |
r1, r2/m, cl/#n |
Shift duplo para a esquerda. |
Shift r1 left by cl/#n, filling with the top bits of r2/m. O último bit deslocado é colocado no transporte.
SHRD |
r1, r2/m, cl/#n |
Shift duplo para a direita. |
Shift r1 right by cl/#n, filling with the bottom bits of r2/m. O último bit deslocado é colocado no transporte.
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. |
Rotação é como mudar, exceto que os bits que são deslocados para fora reaparecem como os bits de preenchimento de entrada. A versão da linguagem C das instruções de rotação incorpora o bit de transporte na rotação.
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. |
Fluxo de Controle
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 |
Devolução |
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. |
Essas instruções são remanescentes da herança CISC do x86 e, em processadores recentes, são, na verdade, mais lentas do que as instruções equivalentes escritas a longo prazo.
Manipulação de cadeia de caracteres
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.
Sinalizadores
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. |
Instruções intertravadas
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 |
Comparar e trocar condicionalmente. |
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:
Variado
INT |
#n |
Interceptar para kernel. |
|
BOUND |
r, m |
Trap if r not in range. |
|
* |
NOP |
No operation. |
|
XLATB |
al = [ebx + al] |
||
BSWAP |
r |
Trocar ordem de bytes no registro. |
Here is a special case of the int instruction.
INT |
3 |
Interceptação de ponto de interrupção do depurador. |
The opcode for INT 3 is 0xCC. The opcode for NOP is 0x90.
Ao depurar o código, talvez seja necessário corrigir algum código. Você pode fazer isso substituindo os bytes ofensivos por 0x90.
Idiomas
XOR |
r, r |
r = 0 |
|
TEST |
r, r |
Check if r = 0. |
|
* |
ADD |
r, r |
Shift r left by 1. |