Compartir a través de


Arquitectura x86

El procesador Intel x86 usa una arquitectura compleja del equipo del conjunto de instrucciones (CISC), lo que significa que hay un número modesto de registros de propósito especial en lugar de grandes cantidades de registros de uso general. También significa que las instrucciones complejas de propósito especial prevalecerán.

El procesador x86 realiza un seguimiento de su herencia al menos hasta el procesador Intel 8080 de 8 bits. Muchas peculiaridades del conjunto de instrucciones x86 se deben a la compatibilidad con versiones anteriores con ese procesador (y con su variante Zilog Z-80).

Microsoft Win32 usa el procesador x86 en modo plano de 32 bits. Esta documentación se centrará solo en el modo plano.

Registros

La arquitectura x86 consta de los siguientes registros enteros sin privilegios.

Eax

Acumulador

Ebx

Registro base

ecx

Registro de contadores

Edx

Registro de datos: se puede usar para el acceso al puerto de E/S y las funciones aritméticas.

Esi

Registro de índice de origen

Edi

Registro de índice de destino

Ebp

Registro de puntero base

Esp

Puntero de pila

Todos los registros enteros son de 32 bits. Sin embargo, muchos de ellostienenssless de 16 o 8 bits.

ax

Bajo 16 bits de eax

Bx

16 bits bajos de ebx

cx

16 bits bajos de ecx

dx

16 bits bajos de edx

si

Bajo 16 bits de esi

di

16 bits bajos de edi

Bp

Bajo 16 bits de ebp

sp

16 bits bajos de esp

al

Bajo 8 bits de eax

ah

8 bits altos de ax

Bl

8 bits bajos de ebx

Bh

Alto 8 bits de bx

Cl

8 bits bajos de ecx

ch

8 bits altos de cx

Dl

8 bits bajos de edx

Dh

8 bits altos de dx

El funcionamiento de un subregión afecta únicamente al subsubsester y a ninguna de las partes fuera de ella. Por ejemplo, el almacenamiento en el registro de ejes deja sin cambios los 16 bits altos del registro de eax .

Al usar ? (Evaluar expresión) command, los registros deben tener el prefijo "at" sign ( @ ). Por ejemplo, debe usar ? @ax en lugar de ? ax. Esto garantiza que el depurador reconozca ax como un registro en lugar de un símbolo.

Sin embargo, el comando (@) no es necesario en el comando r (Registers). Por ejemplo, r ax=5 siempre se interpretará correctamente.

Otros dos registros son importantes para el estado actual del procesador.

Eip

puntero de instrucción

flags

flags

El puntero de instrucción es la dirección de la instrucción que se está ejecutando.

El registro de marcas es una colección de marcas de un solo bit. Muchas instrucciones modifican las marcas para describir el resultado de la instrucción. A continuación, estas marcas se pueden probar mediante instrucciones de salto condicional. Consulte marcas x86 para obtener más información.

Convenciones de llamada

La arquitectura x86 tiene varias convenciones de llamada diferentes. Afortunadamente, todos siguen las mismas reglas de conservación de registros y devolución de función:

  • Las funciones deben conservar todos los registros, excepto eax, ecx y edx, que se pueden cambiar a través de una llamada de función, y esp, que se deben actualizar según la convención de llamada.

  • El registro eax recibe valores devueltos de función si el resultado es de 32 bits o más pequeños. Si el resultado es de 64 bits, el resultado se almacena en el par edx:eax .

A continuación se muestra una lista de las convenciones de llamada usadas en la arquitectura x86:

  • Win32 (__stdcall)

    Los parámetros de función se pasan en la pila, se insertan de derecha a izquierda y el destinatario limpia la pila.

  • Llamada de método nativa de C++ (también conocida como thiscall)

    Los parámetros de función se pasan en la pila, se insertan de derecha a izquierda, el puntero "this" se pasa en el registro ecx y el destinatario limpia la pila.

  • COM (__stdcall para llamadas de método de C++)

    Los parámetros de función se pasan en la pila, se insertan de derecha a izquierda, luego se inserta el puntero "this" en la pila y, a continuación, se llama a la función . El destinatario de la llamada limpia la pila.

  • __fastcall

    Los dos primeros argumentos DWORD o más pequeños se pasan en los registros ecx y edx . Los parámetros restantes se pasan en la pila, insertados de derecha a izquierda. El destinatario de la llamada limpia la pila.

  • __cdecl

    Los parámetros de función se pasan en la pila, se insertan de derecha a izquierda y el autor de la llamada limpia la pila. La convención de llamada __cdecl se usa para todas las funciones con parámetros de longitud variable.

Visualización del depurador de registros y marcas

Este es un ejemplo de visualización del registro del depurador:

eax=00000000 ebx=008b6f00 ecx=01010101 edx=ffffffff esi=00000000 edi=00465000
eip=77f9d022 esp=05cffc48 ebp=05cffc54 iopl=0         nv up ei ng nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000286

En la depuración en modo de usuario, puede omitir el iopl y toda la última línea de la pantalla del depurador.

Marcas x86

En el ejemplo anterior, los códigos de dos letras al final de la segunda línea son marcas. Se trata de registros de un solo bit y tienen una variedad de usos.

En la tabla siguiente se enumeran las marcas x86:

Código de marca Nombre de marca Valor Estado de la marca Descripción
de Marca de desbordamiento 0 1 nvov Sin desbordamiento: desbordamiento
df Marca de dirección 0 1 updn Dirección hacia arriba: dirección hacia abajo
if Marca de interrupción 0 1 diei Interrupciones deshabilitadas: interrupciones habilitadas
sf Sign Flag 0 1 plng Positivo (o cero): negativo
Zf Marca cero 0 1 nzzr Distinto de cero
af Bandera auxiliar de transporte 0 1 Naac Sin transporte auxiliar - Transporte auxiliar
pf Marca de paridad 0 1 Pepo Paridad impar: paridad paridad
cf Marca de transporte 0 1 nccy Sin transporte - Transporte
Tf Marca de captura Si tf es igual a 1, el procesador generará una excepción de STATUS_SINGLE_STEP después de la ejecución de una instrucción. Un depurador usa esta marca para implementar el seguimiento de un solo paso. Otras aplicaciones no deben usarla.
iopl Nivel de privilegios de E/S Nivel de privilegio de E/S Este es un entero de dos bits, con valores entre cero y 3. El sistema operativo lo usa para controlar el acceso al hardware. Las aplicaciones no deben usarla.

Cuando los registros se muestran como resultado de algún comando en la ventana Comando del depurador, es el estado de la marca que se muestra. Sin embargo, si desea cambiar una marca mediante el comando r (Registers), debe hacer referencia a ella mediante el código de marca.

En la ventana Registros de WinDbg, el código de marca se usa para ver o modificar marcas. No se admite el estado de la marca.

Este es un ejemplo. En la presentación del registro anterior, aparece el estado de la marca ng . Esto significa que la marca de signo está establecida actualmente en 1. Para cambiar esto, use el siguiente comando:

r sf=0

Esto establece la marca de signo en cero. Si hace otra presentación de registro, no aparecerá el código de estado ng . En su lugar, se mostrará el código de estado pl .

La marca de signo, la marca cero y la marca de transporte son las marcas más usadas.

Condiciones

Una condición describe el estado de una o varias marcas. Todas las operaciones condicionales de x86 se expresan en términos de condiciones.

El ensamblador usa una abreviatura de una o dos letras para representar una condición. Una condición se puede representar mediante varias abreviaturas. Por ejemplo, AE ("arriba o igual") es la misma condición que NB ("no a continuación"). En la tabla siguiente se enumeran algunas condiciones comunes y su significado.

Nombre de condición Marcas Significado

Z

ZF=1

El resultado de la última operación era cero.

NZ

ZF=0

El resultado de la última operación no era cero.

C

CF=1

La última operación requería un transporte o préstamo. (Para enteros sin signo, esto indica desbordamiento).

NC

CF=0

La última operación no requería un transporte ni un préstamo. (Para enteros sin signo, esto indica desbordamiento).

S

SF=1

El resultado de la última operación tiene su conjunto de bits alto.

NS

SF=0

El resultado de la última operación tiene su bit alto claro.

O

OF=1

Cuando se trata como una operación de entero con signo, la última operación provocó un desbordamiento o subflujo.

No

OF=0

Cuando se trata como operación de entero con signo, la última operación no provocó un desbordamiento ni un flujo inferior.

Las condiciones también se pueden usar para comparar dos valores. La instrucción cmp compara sus dos operandos y, a continuación, establece marcas como si restasen un operando del otro. Las condiciones siguientes se pueden usar para comprobar el resultado de cmpvalue1, value2.

Nombre de condición Marcas Significado después de una operación CMP.

E

ZF=1

value1 == value2.

NE

ZF=0

value1 != value2.

GE NL

SF=OF

value1>= value2. Los valores se tratan como enteros con signo.

LE NG

ZF=1 o SF!=OF

value1<= value2. Los valores se tratan como enteros con signo.

G NLE

ZF=0 y SF=OF

value1>value2. Los valores se tratan como enteros con signo.

L NGE

SF!=OF

value1<value2. Los valores se tratan como enteros con signo.

AE NB

CF=0

value1>= value2. Los valores se tratan como enteros sin signo.

BE NA

CF=1 o ZF=1

value1<= value2. Los valores se tratan como enteros sin signo.

Una NBE

CF=0 y ZF=0

value1>value2. Los valores se tratan como enteros sin signo.

B NAE

CF=1

value1<value2. Los valores se tratan como enteros sin signo.

Las condiciones se suelen usar para actuar sobre el resultado de una instrucción cmp o test . Por ejemplo,

cmp eax, 5
jz equal

compara el registro eax con el número 5 calculando la expresión (eax - 5) y estableciendo marcas según el resultado. Si el resultado de la resta es cero, se establecerá la marca zr y la condición jz será true para que se tome el salto.

Tipos de datos

  • byte: 8 bits

  • word: 16 bits

  • dword: 32 bits

  • qword: 64 bits (incluye dobles de punto flotante)

  • tword: 80 bits (incluye dobles extendidos de punto flotante)

  • oword: 128 bits

Notación

En la tabla siguiente se indica la notación utilizada para describir las instrucciones del lenguaje de ensamblado.

Notation Significado

r, r1, r2...

Registros

m

Dirección de memoria (consulte la sección Modos de direccionamiento correctos para obtener más información).

#n

Constante inmediata

r/m

Registro o memoria

r/#n

Registrar o constante inmediata

r/m/#n

Registro, memoria o constante inmediata

Cc

Código de condición que aparece en la sección Condiciones anteriores.

T

"B", "W" o "D" (byte, word o dword)

accT

Acumulador de tamaño T : al if T = "B", ax if T = "W" o eax si T = "D"

Modos de direccionamiento

Hay varios modos de direccionamiento diferentes, pero todos toman la forma T ptr [expr], donde T es algún tipo de datos (consulte la sección Tipos de datos anteriores) y expr es alguna expresión que implica constantes y registros.

La notación de la mayoría de los modos se puede deducir sin mucha dificultad. Por ejemplo, BYTE PTR [esi+edx*8+3] significa "tomar el valor del registro esi , agregarlo ocho veces el valor del registro edx , agregar tres y luego acceder al byte en la dirección resultante".

Pipelining

Pentium es de doble problema, lo que significa que puede realizar hasta dos acciones en un tic de reloj. Sin embargo, las reglas de cuando es capaz de realizar dos acciones a la vez (conocidas como emparejamiento) son muy complicadas.

Dado que x86 es un procesador CISC, no tiene que preocuparse por las ranuras de retraso de salto.

Acceso a memoria sincronizada

Las instrucciones de carga, modificación y almacenamiento pueden recibir un prefijo de bloqueo , que modifica la instrucción como se indica a continuación:

  1. Antes de emitir la instrucción, la CPU vaciará todas las operaciones de memoria pendientes para garantizar la coherencia. Se abandonan todas las capturas previas de datos.

  2. Al emitir la instrucción, la CPU tendrá acceso exclusivo al bus. Esto garantiza la atomicidad de la operación load/modify/store.

La instrucción xchg obedece automáticamente las reglas anteriores siempre que intercambia un valor con memoria.

Todas las demás instrucciones están predeterminadas en nonlocking.

Predicción de salto

Se predice que se toman saltos incondicionales.

Se predice que se realizarán o no saltos condicionales, en función de si se tomaron la última vez que se ejecutaron. La memoria caché del historial de saltos de grabación tiene un tamaño limitado.

Si la CPU no tiene un registro de si se tomó o no el salto condicional la última vez que se ejecutó, predice los saltos condicionales hacia atrás según se toman y reenvía los saltos condicionales según no se toman.

Alineación

El procesador x86 corregirá automáticamente el acceso a la memoria no asignada, con una penalización de rendimiento. No se genera ninguna excepción.

Un acceso a memoria se considera alineado si la dirección es un entero múltiplo del tamaño del objeto. Por ejemplo, todos los accesos BYTE se alinean (todo es un entero múltiplo de 1), los accesos de WORD a direcciones pares están alineados y las direcciones DWORD deben ser un múltiplo de 4 para que se alineen.

No se debe usar el prefijo de bloqueo para los accesos de memoria no asignados.