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 traza su patrimonio 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 solo se centrará 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 a puertos de E/S y 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 ellos tienen subregistros de 16 bits o 8 bits.

ax

16 bits bajos de eax

bx

16 bits bajos de ebx

cx

16 bits bajos de ecx

dx

16 bits bajos de edx

si

16 bits bajos de esi

di

16 bits bajos de edi

bp

16 bits bajos de ebp

sp

16 bits bajos de esp

al

8 bits bajos de eax

ah

8 bits altos de ax

bl

8 bits bajos de ebx

bh

8 bits altos 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 en un subregistro afecta solo al subregistro y a ninguna de las partes fuera del subregistro. Por ejemplo, el almacenamiento en el registro ax no modifica los 16 bits altos del registro eax.

Al usar el ? (Evaluar expresión) comando, los registros deben tener como prefijo un signo "at" ( @ ). 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án correctamente.

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

eip

puntero de instrucción

marcas

Banderas

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. Estas marcas pueden ser comprobadas por instrucciones de salto condicional. Vea Marcas x86 para más detalles.

Convenciones de llamada

La arquitectura x86 tiene varias convenciones de llamada diferentes. Afortunadamente, todas siguen las mismas reglas de preservación de registros y de retorno de funciones:

  • Las funciones deben conservar todos los registros, excepto eax, ecx y edx, que pueden modificarse en una llamada a función, y esp, que debe actualizarse según la convención de llamada.

  • El registro eax recibe los valores de retorno de la función si el resultado es de 32 bits o menor. 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 que se usan en la arquitectura x86:

  • Win32 (__stdcall)

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

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

    Los parámetros de la función se pasan a la pila, se empujan de derecha a izquierda, el puntero "this" se pasa al 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 receptor limpia la pila.

  • __fastcall

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

  • __cdecl

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

Visualización de registros y marcas en el depurador

A continuación se muestra un ejemplo de visualización de registros 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 usuario, puede ignorar el iopl y toda la última línea de la pantalla del depurador.

Banderas x86

En el ejemplo anterior, los códigos de dos letras al final de la segunda línea son marcas. Estos son 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 bandera Descripción
of Marca de desbordamiento 0 1 nvov Sin desbordamiento - Desbordamiento
df Bandera de dirección 0 1 updn Dirección arriba - Dirección abajo
si Marca de interrupción 0 1 diei Interrupciones desactivadas - Interrupciones activadas
sf Marca de señal 0 1 plng Positivo (o cero): negativo
zf Marca cero 0 1 nzzr No cero - Cero
af Marca de transporte auxiliar 0 1 naac Sin transporte auxiliar - transporte auxiliar
pf Marca de paridad 0 1 pepo Paridad par - Paridad impar
cf Marca de transporte 0 1 nccy Sin transporte - Transporte
tf Marca de trampa Si tf es igual a 1, el procesador generará una excepción STATUS_SINGLE_STEP después de la ejecución de una instrucción. Esta marca es utilizada por un depurador para implementar el rastreo de un solo paso. No debe usarse en otras aplicaciones.
iopl Nivel de privilegios de E/S Nivel de privilegios 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 de comandos del depurador, es el estado del indicador lo que se muestra. Sin embargo, si desea cambiar una bandera mediante el comando r (Registers), debe hacer referencia a ella mediante el código de bandera .

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

Este es un ejemplo. En la visualización del registro anterior, aparece el estado de 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 pone la marca de signo a cero. Si realiza otra visualización de registro, el código de estado ng no aparecerá. 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 o dos abreviaturas de letra para representar una condición. Una condición se puede representar mediante varias abreviaturas. Por ejemplo, AE ("mayor o igual") es la misma condición que NB ("no inferior"). En la tabla siguiente se enumeran algunas condiciones comunes y su significado.

Nombre de condición Banderas Significado

Z

ZF=1

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

NZ

ZF=0

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

C

CF=1

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

NC

CF=0

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

S

SF=1

El resultado de la última operación tiene el bit alto activado.

NS

SF=0

El resultado de la última operación tiene el bit alto despejado.

O

OF=1

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

NO

OF=0

Cuando se trata como una operación de número entero con signo, la última operación no causó un desbordamiento o subdesbordamiento.

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

Nombre de la condición Banderas 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 dirección 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 utilizan normalmente para actuar sobre el resultado de una instrucción cmp o de prueba. Por ejemplo

cmp eax, 5
jz equal

compara el registro eax con el número 5 calculando la expresión (eax - 5) y activando las marcas según el resultado. Si el resultado de la resta es cero, entonces se activará la marca zr, y la condición jz será verdadera por lo que se realizará el salto.

Tipos de datos

  • byte: 8 bits

  • word: 16 bits

  • dword: 32 bits

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

  • tword: 80 bits (incluye doubles 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.

Notación Significado

r, r1, r2...

Registros

m

Dirección de memoria (consulte la sección sobre modos de direccionamiento que sigue para obtener más información).

#n

Constante inmediata

r/m

Registro o memoria

r/#n

Registro o constante inmediata

r/m/#n

Registro, memoria o constante inmediata

cc

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

T

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

accT

Tamaño T acumulador: al si T = "B", ax si 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 (vea la sección Tipos de datos anteriores) y expr es una expresión que implica constantes y registros.

La notación para 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, sumarle ocho veces el valor del registro edx, sumar tres, y a continuación, acceder al byte en la dirección resultante".

Canalización

El Pentium es dual-issue, lo que significa que puede realizar hasta dos acciones en un tick de reloj. Sin embargo, las reglas sobre cuándo es capaz de realizar dos acciones a la vez (lo que se conoce como emparejamiento) son muy complicadas.

Como x86 es un procesador CISC, no tiene que preocuparse por las ranuras de retardo 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 sigue:

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

  2. Al ejecutar la instrucción, la CPU tendrá acceso exclusivo al bus de datos. Esto garantiza la atomicidad de la operación de carga/modificación/almacenamiento.

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

Todas las demás instrucciones, por defecto, no son bloqueantes.

Predicción de saltos

Se predice que se realizarán saltos incondicionales.

Se predice que los saltos condicionales se realizarán o no, dependiendo de si se realizaron la última vez que se ejecutaron. La caché para registrar el historial de saltos 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 como tomados y los saltos condicionales hacia adelante como no tomados.

Alineación

El procesador x86 corregirá automáticamente el acceso a la memoria no alineado, con una penalización en el 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 están alineados (todo es un entero múltiplo de 1), los accesos de WORD a direcciones uniformes están alineados y las direcciones DWORD deben ser un múltiplo de 4 para alinearse.

El prefijo de bloqueo no debe usarse para accesos a memoria desalineados.

Consulte también

x64 Architecture

X86-64 en Wikipedia