Compartir a través de


Instrucciones de x86

En las listas de esta sección, las instrucciones marcadas con un asterisco (*) son especialmente importantes. Las instrucciones no tan marcadas no son críticas.

En el procesador x86, las instrucciones tienen un tamaño variable, por lo que el desensamblado hacia atrás es un ejercicio de coincidencia de patrones. Para desensamblar hacia atrás desde una dirección, debe empezar a desensamblar en un punto más allá de lo que realmente desea ir y, a continuación, mirar hacia adelante hasta que las instrucciones empiecen a tener sentido. Es posible que las primeras instrucciones no tengan sentido porque es posible que haya empezado a desensamblar en medio de una instrucción. Por desgracia, existe la posibilidad de que el desensamblado nunca se sincronice con el flujo de instrucciones y tendrá que intentar desensamblar en un punto de partida diferente hasta que encuentre un punto de partida que funcione.

En el caso de las instrucciones switch bien empaquetadas, el compilador emite datos directamente en el flujo de código, por lo que el desensamblado a través de una instrucción switch normalmente se encontrará en instrucciones que no tienen sentido (porque son realmente datos). Busque el final de los datos y continúe desensamblado allí.

Notación de instrucción

La notación general para obtener instrucciones es colocar el registro de destino a la izquierda y el origen a la derecha. Sin embargo, puede haber algunas excepciones a esta regla.

Las instrucciones aritméticas suelen ser dos registros con los registros de origen y destino que combinan. El resultado se almacena en el destino.

Algunas de las instrucciones tienen versiones de 16 y 32 bits, pero aquí solo se enumeran las versiones de 32 bits. No se enumeran aquí instrucciones de punto flotante, instrucciones con privilegios e instrucciones que se usan solo en modelos segmentados (que Microsoft Win32 no usa).

Para ahorrar espacio, muchas de las instrucciones se expresan en forma combinada, como se muestra en el ejemplo siguiente.

*

MOV

r1, r/m/#n

r1 = r/m/#n

significa que el primer parámetro debe ser un registro, pero el segundo puede ser un registro, una referencia de memoria o un valor inmediato.

Para ahorrar aún más espacio, las instrucciones también se pueden expresar como se muestra en lo siguiente.

*

MOV

r1/m, r/m/#n

r1/m = r/m/#n

lo que significa que el primer parámetro puede ser un registro o una referencia de memoria, y el segundo puede ser un registro, una referencia de memoria o un valor inmediato.

A menos que se indique lo contrario, cuando se usa esta abreviatura, no puede elegir la memoria para el origen y el destino.

Además, se puede anexar un sufijo de tamaño de bits (8, 16, 32) al origen o destino para indicar que el parámetro debe ser de ese tamaño. Por ejemplo, r8 significa un registro de 8 bits.

Memoria, transferencia de datos y conversión de datos

Las instrucciones de transferencia de memoria y datos no afectan a las marcas.

Dirección efectiva

*

LEA

r, m

Carga de la dirección efectiva.

(r = dirección de m)

Por ejemplo, LEA eax, [esi+4] significa eax = esi + 4. Esta instrucción se usa a menudo para realizar aritméticas.

Transferencia de datos

MOV

r1/m, r2/m/#n

r1/m = r/m/#n

MOVSX

r1, r/m

Mover con la extensión de signo.

*

MOVZX

r1, r/m

Mover con una extensión cero.

MOVSX y MOVZX son versiones especiales de la instrucción mov que realizan la extensión de signo o ninguna extensión del origen al destino. Esta es la única instrucción que permite que el origen y el destino sean diferentes tamaños. (Y, de hecho, deben ser diferentes tamaños.

Manipulación de la pila

El registro esp apunta a la pila. El valor en esp es la parte superior de la pila (más recientemente insertado, primero que se va a extraer); Los elementos de pila más antiguos residen en direcciones superiores.

INSERTAR

r/m/#n

Insertar valor en la pila.

POP

r/m

Valor pop de la pila.

PUSHFD

Inserte marcas en la pila.

POPFD

Pop flags from stack(Marcas emergentes de la pila).

PUSHAD

Inserte todos los registros enteros.

POPAD

Pop all integer registers.

ENTRAR

#n, #n

Crear marco de pila.

*

SALIR

Desmontar marco de pila

El compilador de C/C++ no usa la instrucción enter . (La instrucción enter se usa para implementar procedimientos anidados en lenguajes como Algol o Pascal).

La instrucción leave es equivalente a:

mov esp, ebp
pop ebp

Conversión de datos

CBW

Convertir byte (al) en palabras (ax).

CWD

Convierta word (ax) en dword (dx:ax).

CWDE

Convierta word (ax) en dword (eax).

CDQ

convierta dword (eax) en qword (edx:eax).

Todas las conversiones realizan la extensión de signo.

Manipulación aritmética y bit

Todas las instrucciones de manipulación aritmética y bit modifican marcas.

Aritmética

ADD

r1/m, r2/m/#n

r1/m += r2/m/#n

ADC

r1/m, r2/m/#n

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

SUB

r1/m, r2/m/#n

r1/m -= r2/m/#n

SBB

r1/m, r2/m/#n

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

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

Proceso r1/m: r2/m/#n

La instrucción cmp calcula la resta y establece marcas según el resultado, pero produce el resultado. Normalmente va seguido de una instrucción de salto condicional que prueba el resultado de la resta.

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

Multiplicación sin signo y firmada. El estado de las marcas después de la multiplicación no está definido.

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

División sin firmar y firmada. El primer registro de la explicación de pseudocódigo recibe el resto y el segundo recibe el cociente. Si el resultado desborda el destino, se genera una excepción de desbordamiento de división.

El estado de las marcas después de la división no está definido.

*

SETcc

r/m8

Establecer r/m8 en 0 o 1

Si la condición cc es true, el valor de 8 bits se establece en 1. De lo contrario, el valor de 8 bits se establece en cero.

Decimal codificado binario

No verá estas instrucciones a menos que esté depurando código escrito en COBOL.

DAA

Ajuste decimal después de la adición.

DAS

Ajuste decimal después de la resta.

Estas instrucciones ajustan el registro al después de realizar una operación decimal codificada binaria empaquetada.

AAA

ASCII se ajusta después de la adición.

AAS

Ajuste ASCII después de la resta.

Estas instrucciones ajustan el registro al después de realizar una operación decimal codificada binaria desempaquetada.

AAM

ASCII se ajusta después de la multiplicación.

AAD

Ajuste ASCII después de la división.

Estas instrucciones ajustan los registros al y ah después de realizar una operación decimal codificada binaria desempaquetada.

Bits

AND

r1/m, r2/m/#n

r1/m = r1/m y r2/m/#n

O BIEN

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 a bit not r1/m

*

PRUEBA

r1/m, r2/m/#n

Proceso r1/m y r2/m/#n

La instrucción de prueba calcula el operador AND lógico y establece marcas según el resultado, pero elimina el resultado. Normalmente va seguida de una instrucción de salto condicional que prueba el resultado del AND lógico.

SHL

r1/m, cl/#n

r1/m <<= cl/#n

SHR

r1/m, cl/#n

r1/m >>= cl/#n relleno cero

*

SAR

r1/m, cl/#n

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

El último bit desplazado se coloca en la carga.

SHLD

r1, r2/m, cl/#n

Mayús doble a la izquierda.

Mayús r1 a la izquierda por cl/#n, rellenando con los bits superiores de r2/m. El último bit desplazado se coloca en la carga.

SHRD

r1, r2/m, cl/#n

Desplazá a la derecha doble.

Mayús r1 a la derecha por cl/#n, rellenando con los bits inferiores de r2/m. El último bit desplazado se coloca en la carga.

ROL

r1, cl/#n

Gire r1 a la izquierda por cl/#n.

ROR

r1, cl/#n

Gire r1 a la derecha por cl/#n.

RCL

r1, cl/#n

Gire r1/C a la izquierda por cl/#n.

RCR

r1, cl/#n

Gire r1/C a la derecha por cl/#n.

La rotación es como cambiar, excepto que los bits que se desplazan se vuelven a aparecer como los bits de relleno entrantes. La versión del lenguaje C de las instrucciones de rotación incorpora el bit de transporte a la rotación.

BT

r1, r2/#n

Copie el bit r2/#n de r1 en transporte.

BTS

r1, r2/#n

Establezca bit r2/#n de r1, copie el valor anterior en carry.

BTC

r1, r2/#n

Borre el bit r2/#n de r1 y copie el valor anterior en la carga.

Flujo de control

Jcc

Dest

Condicional de rama.

JMP

Dest

Salta directamente.

JMP

r/m

Saltar indirecto.

CALL

Dest

Llame directo.

*

CALL

r/m

Llame a indirecto.

La instrucción de llamada inserta la dirección de retorno en la pila y, a continuación, salta al destino.

*

RET

#n

Valor devuelto

La instrucción ret aparece y salta a la dirección de retorno de la pila. Un #n distinto de cero en la instrucción RET indica que después de extraer la dirección de retorno, el valor #n debe agregarse al puntero de pila.

BUCLE

Disminuir ecx y saltar si result es distinto de cero.

LOOPZ

Disminuir ecx y saltar si result es distinto de cero y zr se estableció.

LOOPNZ

Disminuir ecx y saltar si el resultado es distinto de cero y zr estaba claro.

JECXZ

Saltar si ecx es cero.

Estas instrucciones son restos del patrimonio CISC de x86 y en procesadores recientes son realmente más lentos que las instrucciones equivalentes escritas durante mucho tiempo.

Manipulación de cadenas

MOVST

Mover T de esi a edi.

CMPS T

Compare T de esi con edi.

SCAS T

Escanear T desde edi para accT.

LODST

Cargue T de esi enacc T.

STOST

Almacenar T a edi desdeacc T.

Después de realizar la operación, el registro de origen y destino se incrementa o disminuye según sizeof(T), según el valor de la marca de dirección (arriba o abajo).

Rep puede prefijar la instrucción para repetir la operación el número de veces especificado por el registro ecx .

La instrucción rep mov se usa para copiar bloques de memoria.

La instrucción rep stos se usa para rellenar un bloque de memoria con accT.

Banderas

LAHF

Cargue ah desde marcas.

SAHF

Almacenar ah en marcas.

STC

Defina la carga.

CLC

Transporte claro.

CMC

Transporte complementario.

STD

Establezca la dirección en abajo.

CLD

Establezca la dirección hacia arriba.

STI

Habilite las interrupciones.

CLI

Deshabilite las interrupciones.

Instrucciones interbloqueadas

XCHG

r1, r/m

Intercambiar r1 y r/m.

XADD

r1, r/m

Agregue r1 a r/m, coloque el valor original en r1.

CMPXCHG

r1, r/m

Compare e intercambie condicional.

La instrucción cmpxchg es la versión atómica de lo siguiente:

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

Misceláneos

INT

#n

Interceptar al kernel.

LÍMITE

r, m

Interceptar si r no está dentro del intervalo.

*

NOP

No hay ninguna operación.

XLATB

al = [ebx + al]

BSWAP

r

Intercambiar el orden de bytes en el registro.

Este es un caso especial de la instrucción int .

INT

3

Captura de punto de interrupción del depurador.

El código de operación de INT 3 es 0xCC. El código de operación para NOP es 0x90.

Al depurar código, es posible que tenga que aplicar revisiones a algún código. Para ello, reemplace los bytes infractores por 0x90.

Idiomas

XOR

r, r

r = 0

PRUEBA

r, r

Compruebe si r = 0.

*

ADD

r, r

Mayús r a la izquierda por 1.