Intel x86 Assembly Language & Microarchitecture
Fundamentos del registro
Buscar..
Registros de 16 bits
Cuando Intel definió el 8086 original, era un procesador de 16 bits con un bus de direcciones de 20 bits (ver más abajo). Definieron 8 registros de propósito general de 16 bits, pero les dieron roles específicos para ciertas instrucciones:
-
AXel registro del acumulador.
Muchos opcodes asumieron este registro o fueron más rápidos si se especificaron. -
DXEl registro de datos.
Esto a veces se combinaba como el alto 16 bits de un valor de 32 bits conAX, por ejemplo, como resultado de una multiplicación. -
CXEl registro de la cuenta.
Esto se usó en varias instrucciones orientadas a bucles como contador implícito para esos bucles, por ejemplo,LOOPNE(bucle si no es igual) yREP(movimiento / comparación repetidos) -
BXEl registro base.
Esto podría usarse para indexar la base de una estructura en la memoria; ninguno de los registros anteriores se podría usar para indexar directamente en la memoria. -
SIEl registro de índice de fuente.
Este fue el índice de fuente implícito en la memoria para ciertas operaciones de movimiento y comparación. -
DIEl registro del índice de destino.
Este fue el índice de destino implícito en la memoria para ciertas operaciones de movimiento y comparación. -
SPEl registro Stack Pointer.
¡Este es el registro de propósitos menos generales en el set! Señaló la posición actual en la pila, que se usó explícitamente para las operacionesPUSHyPOP, implícitamente paraCALLyRETcon subrutinas, y MUY implícitamente durante las interrupciones. Como tal, usarlo para cualquier otra cosa era peligroso para su programa. -
BPEl registro de puntero base.
Cuando las subrutinas llaman a otras subrutinas, la pila contiene múltiples "marcos de pila".BPpodría utilizarse para mantener el marco de pila actual, y luego, cuando se llamara una nueva subrutina, se podría guardar en la pila, se creó y utilizó el nuevo marco de pila y, al regresar de la subrutina interna, se pudo restaurar el antiguo valor del marco de pila .
Notas:
Los tres primeros registros no pueden usarse para indexar en la memoria.
BX,SIyDIpor índice predeterminado en el segmento de datos actual (ver más abajo).MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI, cuando se usa en operaciones de memoria a memoria comoMOVSyCMPS, solo usa el Segmento Extra (ver más abajo). Esto no puede ser anulado.SPyBPusan el Segmento de Apilamiento (ver más abajo) de manera predeterminada.
Registros de 32 bits
Cuando Intel produjo el 80386, se actualizó de un procesador de 16 bits a uno de 32 bits. El procesamiento de 32 bits significa dos cosas: tanto los datos que se manipularon fueron de 32 bits, como las direcciones de memoria a las que se accedió fueron de 32 bits. Para hacer esto, pero aún siendo compatibles con sus procesadores anteriores, introdujeron modos completamente nuevos para el procesador. Se encontraba en modo de 16 bits o en modo de 32 bits, ¡pero se puede anular este modo de forma individualizada para los datos, el direccionamiento o ambos!
En primer lugar, tenían que definir registros de 32 bits. Lo hicieron simplemente extendiendo los ocho existentes de 16 bits a 32 bits y dándoles nombres "extendidos" con un prefijo E : EAX , EBX , ECX , EDX , ESI , EDI , EBP y ESP . Los 16 bits inferiores de estos registros fueron los mismos que antes, pero las mitades superiores de los registros estaban disponibles para operaciones de 32 bits como ADD y CMP . Las mitades superiores no eran accesibles por separado como lo habían hecho con los registros de 8 bits.
El procesador tenía que tener modos separados de 16 y 32 bits porque Intel usaba los mismos códigos de operación para muchas de las operaciones: CMP AX,DX en modo de 16 bits y CMP EAX,EDX en el modo de 32 bits tenía exactamente los mismos códigos de operación ! Esto significaba que el mismo código NO se podía ejecutar en ninguno de los modos:
El código de operación para "Mover inmediatamente a
AX" es0xB8, seguido de dos bytes del valor inmediato:0xB8 0x12 0x34
El código de operación para "Mover inmediatamente a
EAX" es0xB8, seguido de cuatro bytes del valor inmediato:0xB8 0x12 0x34 0x56 0x78
Por lo tanto, el miembro debe saber en qué modo está el procesador cuando ejecuta el código, para que sepa emitir el número correcto de bytes.
Registros de 8 bits
Los primeros cuatro registros de 16 bits podrían tener acceso a sus bytes de la mitad superior e inferior directamente como sus propios registros:
-
AHyALson las mitades altas y bajas del registroAX. -
BHyBLson las mitades Alta y Baja del registroBX. -
CHyCLson las mitades Alta y Baja del registroCX. -
DHyDLson las mitades Alta y Baja del registroDX.
¡Tenga en cuenta que esto significa que alterar AH o AL también alterará inmediatamente AX también! También tenga en cuenta que cualquier operación en un registro de 8 bits no podría afectar a su "socio", lo que incrementaría la AL tal manera que el desbordamiento de 0xFF a 0x00 no alteraría AH .
Los registros de 64 bits también tienen versiones de 8 bits que representan sus bytes inferiores:
-
SILparaRSI -
DILparaRDI -
BPLparaRBP -
SPLparaRSP
Lo mismo se aplica a los registros R8 a R15 : sus respectivas partes de byte inferior se denominan R8B - R15B .
Registros de segmento
Segmentación
Cuando Intel estaba diseñando el 8086 original, ya existían varios procesadores de 8 bits que tenían capacidades de 16 bits, pero querían producir un verdadero procesador de 16 bits. También querían producir algo mejor y más capaz que lo que ya existía, por lo que querían poder acceder a más del máximo de 65,536 bytes de memoria implícitos en los registros de direccionamiento de 16 bits.
Registros del segmento original
Así que implementaron la idea de "Segmentos", un bloque de memoria de 64 kilobytes indexado por los registros de direcciones de 16 bits, que se podrían basar para abordar diferentes áreas de la memoria total. Para mantener estas bases de segmento, se incluyeron Registros de Segmento:
-
CSEl registro del segmento de código.
Esto contiene el segmento del código que se está ejecutando actualmente, indexado por el registro deIP(puntero de instrucción) implícito. -
DSEl registro del segmento de datos.
Esto contiene el segmento predeterminado para los datos que están siendo manipulados por el programa. -
ESEl registro de Segmento Extra.
Esto contiene un segundo segmento de datos, para operaciones de datos simultáneas en la memoria total. -
SSEl registro del segmento de pila.
Esto contiene el segmento de memoria que contiene la pila actual.
Tamaño del segmento?
Los registros de segmento pueden ser de cualquier tamaño, pero hacer que tengan 16 bits de ancho facilita la interoperación con los otros registros. La siguiente pregunta fue: ¿deberían superponerse los segmentos y, de ser así, cuánto? La respuesta a esa pregunta determinaría el tamaño de memoria total al que se podría acceder.
Si no hubiera ninguna superposición, entonces el espacio de direcciones sería de 32 bits (4 gigabytes), ¡un tamaño totalmente insólito en ese momento! Una superposición más "natural" de 8 bits produciría un espacio de direcciones de 24 bits, o 16 megabytes. Al final, Intel decidió guardar cuatro pines de dirección más en el procesador al hacer que el espacio de direcciones de 1 megabyte con una superposición de 12 bits, ¡consideraron que esto era lo suficientemente grande para el tiempo!
Más registros de segmento!
Cuando Intel estaba diseñando el 80386, reconocieron que la suite existente de 4 Registros de segmento no era suficiente para la complejidad de los programas que querían que fuera compatible. Así que agregaron dos más:
-
FSEl registro del segmento lejano -
GSEl registro del segmento global
Estos nuevos registros de Segmento no tenían ningún uso forzado por el procesador: estaban simplemente disponibles para lo que el programador quisiera.
Algunos dicen que los nombres fueron elegidos para simplemente continuar con el tema
C,D,Edel conjunto existente ...
Registros de 64 bits
AMD es un fabricante de procesadores que ha licenciado el diseño del 80386 de Intel para producir versiones compatibles, pero de la competencia. Hicieron cambios internos en el diseño para mejorar el rendimiento u otras mejoras al diseño, al mismo tiempo que podían ejecutar los mismos programas.
Para unir a Intel, crearon extensiones de 64 bits para el diseño de Intel de 32 bits y produjeron el primer chip de 64 bits que aún podía ejecutar código x86 de 32 bits. Intel terminó siguiendo el diseño de AMD en sus versiones de la arquitectura de 64 bits.
El diseño de 64 bits realizó una serie de cambios en el conjunto de registros, a la vez que sigue siendo compatible con versiones anteriores:
- Los registros de propósito general existentes se ampliaron a 64 bits y se nombraron con un prefijo
R:RAX,RBX,RCX,RDX,RSI,RDI,RBPyRSP.Nuevamente, las mitades inferiores de estos registros fueron los mismos registros de prefijo
Eque antes, y no se pudo acceder a las mitades superiores de forma independiente. - Se agregaron 8 registros más de 64 bits, y no se nombraron sino que simplemente se numeraron:
R8,R9,R10,R11,R12,R13,R14yR15.- La mitad baja de 32 bits de estos registros es de
R8DaR15D(D para DWORD como es habitual). - Se puede acceder a los 16 bits más bajos de estos registros colocando una
Wen el nombre del registro:R8WaR15W.
- La mitad baja de 32 bits de estos registros es de
- Ahora se puede acceder a los 8 bits más bajos de los 16 registros:
- Los tradicionales
AL,BL,CLyDL; - Los bytes bajos de los registros de puntero (tradicionalmente):
SIL,DIL,BPLySPL; - Y los bytes bajos de los 8 nuevos registros:
R8BaR15B. - Sin embargo,
AH,BH,CHyDHson inaccesibles en las instrucciones que usan un prefijo REX (para el tamaño del operando de 64 bits, o para acceder a R8-R15, o para acceder aSIL,DIL,BPLoSPL). Con un prefijo REX, el patrón de bits del código de la máquina que solía significarAHsignificaSPL, y así sucesivamente. Consulte la Tabla 3-1 del manual de referencia de instrucciones de Intel (volumen 2).
- Los tradicionales
Escribir en un registro de 32 bits siempre pone a cero los 32 bits superiores del registro de ancho completo, a diferencia de escribir en un registro de 8 o 16 bits (que se combina con el valor antiguo, que es una dependencia adicional para la ejecución fuera de orden) ).
Registro de banderas
Cuando la unidad lógica aritmética (ALU) x86 realiza operaciones como NOT y ADD , marca los resultados de estas operaciones ("se convirtió en cero", "se desbordó", "se convirtió en negativo") en un registro FLAGS especial de 16 bits. Los procesadores de 32 bits lo actualizaron a 32 bits y lo llamaron EFLAGS , mientras que los procesadores de 64 bits lo actualizaron a 64 bits y lo llamaron RFLAGS .
Códigos de condición
Pero no importa el nombre, el registro no es accesible directamente (excepto por un par de instrucciones, consulte a continuación). En cambio, se hace referencia a indicadores individuales en ciertas instrucciones, como Salto condicional o Conjunto condicional, conocidos como Jcc y SETcc donde cc significa "código de condición" y hace referencia a la siguiente tabla:
| Código de condición | Nombre | Definición |
|---|---|---|
E , Z | Igual, cero | ZF == 1 |
NE , NZ | No es igual, no es cero | ZF == 0 |
O | Rebosar | OF == 1 |
NO | Sin desbordamiento | OF == 0 |
S | Firmado | SF == 1 |
NS | No firmado | SF == 0 |
P | Paridad | PF == 1 |
NP | Sin paridad | PF == 0 |
| -------------- | ---- | ---------- |
C , B , NAE | Llevar, debajo, no arriba o igual | CF == 1 |
NC , NB , AE | No llevar, no debajo, arriba o igual | CF == 0 |
A , NBE | Arriba, no abajo o igual | CF == 0 y ZF == 0 |
NA , BE | No arriba, abajo o igual | CF == 1 o ZF == 1 |
| --------------- | ---- | ---------- |
GE , NL | Mayor o igual, no menos | SF == OF |
NGE , L | No mayor o igual, menos | SF ! = OF |
G , NLE | Mayor, no menos o igual | ZF == 0 y SF == OF |
NG , LE | No mayor, menor o igual | ZF == 1 o SF ! = OF |
En 16 bits, restar 1 de 0 es 65,535 o -1 dependiendo de si se usa aritmética sin signo o con signo, pero el destino tiene 0xFFFF cualquier manera. Es solo interpretando los códigos de condición que el significado es claro. Es aún más revelador si 1 se resta de 0x8000 : en aritmética sin signo, eso simplemente cambia 32,768 a 32,767 ; mientras que en la aritmética firmado cambia -32,768 a 32,767 - un desbordamiento mucho más digno de mención!
Los códigos de condición se agrupan en tres bloques en la tabla: sin signo, sin signo y con signo. El nombre dentro de los últimos dos bloques usa "Arriba" y "Abajo" para los que no están firmados, y "Mayor" o "Menos" para los firmados. Así que JB sería "Saltar si está abajo" (sin firmar), mientras que JL sería "Saltar si menos" (firmado).
Accediendo a FLAGS directamente
Los códigos de condición anteriores son útiles para interpretar conceptos predefinidos, pero los bits de marca reales también están disponibles directamente con las siguientes dos instrucciones:
-
LAHFCargar registroAHcon banderas -
SAHFTiendaAHregistro en Banderas
Solo ciertas banderas se copian a través de estas instrucciones. Todo el EFLAGS FLAGS / EFLAGS / RFLAGS se puede guardar o restaurar en la pila:
-
PUSHF/POPFPush / popFLAGS16 bits en / desde la pila -
PUSHFD/POPFDEmpuje /POPFDEFLAGS32 bits en / desde la pila -
PUSHFQ/POPFQpush / pop de 64 bitsRFLAGSen / de la pila
Tenga en cuenta que las interrupciones guardan y restauran el registro actual de [R/E]FLAGS automáticamente.
Otras banderas
Además de los indicadores ALU descritos anteriormente, el registro FLAGS define otros indicadores de estado del sistema:
-
IFla bandera de interrupción.
Esto se configura con la instrucciónSTIpara habilitar interrupciones globalmente, y se borra con la instrucciónCLIpara deshabilitar interrupciones globalmente. -
DFLa bandera de dirección.
Las operaciones de memoria a memoria comoCMPSyMOVS(para comparar y moverse entre ubicaciones de memoria) incrementan o disminuyen automáticamente los registros de índice como parte de la instrucción. El indicadorDFdicta cuál sucede: si se borra con la instrucciónCLD, se incrementan; si se establece con la instrucciónSTD, se decrementan. -
TFLa Bandera De La Trampa. Esta es una bandera de depuración. Al configurarlo, el procesador pasará al modo de "un solo paso": después de que se ejecute cada instrucción, llamará al "Controlador de interrupciones de un solo paso", que se espera sea manejado por un depurador. No hay instrucciones para establecer o borrar este indicador: debe manipular el bit mientras está en la memoria.
80286 Banderas
Para admitir las nuevas instalaciones de multitarea en el 80286, Intel agregó marcas adicionales al registro FLAGS :
-
IOPLEl nivel de privilegio de E / S.
Para proteger el código de multitarea, algunas tareas necesitaban privilegios para acceder a los puertos de E / S, mientras que otras tenían que dejar de acceder a ellos. Intel introdujo una escala de privilegios de cuatro niveles, con002 siendo los más privilegiados y112 siendo los menos. SiIOPLera menor que el Nivel de privilegio actual, cualquier intento de acceder a los puertos de E / S, o habilitar o deshabilitar interrupciones, causaría un error de protección general en su lugar. - Bandera de tarea anidada
NT.
Este indicador se estableció si una TareaCALLotra Tarea, lo que provocó un cambio de contexto. El indicador establecido le dijo al procesador que hiciera un cambio de contexto cuando se ejecutó elRET.
80386 Banderas
El '386 necesitaba banderas adicionales para admitir características adicionales diseñadas en el procesador.
-
RFLa bandera del curriculum vitae.
El `386 agregó registros de depuración, que podrían invocar al depurador en varios accesos de hardware como leer, escribir o ejecutar una determinada ubicación de memoria. Sin embargo, cuando el controlador de depuración regresó para ejecutar la instrucción, el acceso volverá a invocar inmediatamente el controlador de depuración. O al menos lo haría si no fuera por el indicador de reanudación, que se establece automáticamente en la entrada en el controlador de depuración, y se borra automáticamente después de cada instrucción. Si se establece el indicador de reanudación, el controlador de depuración no se invoca. -
VMThe Virtual 8086 Flag.
Para admitir el código de 16 bits más antiguo y el código de 32 bits más nuevo, el 80386 podría ejecutar tareas de 16 bits en un modo "Virtual 8086", con la ayuda de un ejecutivo de Virtual 8086. El indicador deVMindicó que esta tarea era una tarea 8086 virtual.
80486 Banderas
A medida que la arquitectura de Intel mejoró, se aceleró a través de tecnología como cachés y ejecución súper escalar. Eso tenía que optimizar el acceso al sistema haciendo suposiciones. Para controlar esos supuestos, se necesitaban más banderas:
- Indicador de comprobación de alineación de
ACLa arquitectura x86 siempre podría acceder a valores de memoria de múltiples bytes en cualquier límite de bytes, a diferencia de algunas arquitecturas que requerían que estuvieran alineadas con el tamaño (los valores de 4 bytes deben estar en los límites de 4 bytes). Sin embargo, fue menos eficiente hacerlo, ya que se necesitaban múltiples accesos de memoria para acceder a datos no alineados. Si se estableció el indicadorAC, entonces un acceso no alineado provocaría una excepción en lugar de ejecutar el código. De esa manera, el código podría mejorarse durante el desarrollo conACestablecido, pero desactivado para el código de producción.
Banderas Pentium
El Pentium agregó más soporte para la virtualización, más el soporte para la instrucción CPUID :
-
VIFLa bandera de interrupción virtual.
Esta es una copia virtual delIFde esta Tarea, ya sea que esta Tarea desee o no deshabilitar las interrupciones, sin afectar realmente a las Interrupciones globales. -
VIPLa bandera pendiente de interrupción virtual.
Esto indica que una interrupción fue prácticamente bloqueada porVIF, por lo que cuando la Tarea realiza unaSTIpuedeSTIuna interrupción virtual para ella. -
IDLaCPUID-Bandera permitida.
Si se permite o no que esta tarea ejecute la instrucciónCPUID. Un monitor virtual podría no permitirlo y "mentir" a la tarea solicitante si ejecuta la instrucción.