assembler and assembly x86 prefix

assembler - and assembly x86



¿Qué significan los "prefijos de instrucción" en el moderno x86? (2)

Para entender por qué Bulldozer era insatisfactorio, he estado buscando en el excelente libro de microarquitectomía de Agner Fog, en la página 178 debajo del bulldozer tiene este párrafo.

Las instrucciones con hasta tres prefijos pueden decodificarse en un ciclo de reloj. Hay una penalización muy grande para las instrucciones con más de tres prefijos. Las instrucciones con 4-7 prefijos requieren entre 14 y 15 ciclos de reloj adicionales para decodificar. Las instrucciones con 8-11 prefijos toman 20-22 ciclos de reloj adicionales, y las instrucciones con 12-14 prefijos toman 27 - 28 ciclos de reloj adicionales. Por lo tanto, no se recomienda hacer las instrucciones NOP más tiempo con más de tres prefijos. El recuento de prefijos de esta regla incluye el tamaño del operando, el tamaño de la dirección, el segmento, la repetición, el bloqueo, los prefijos REX y XOP. Un prefijo VEX de tres bytes cuenta como uno, mientras que un prefijo VEX de dos bytes no cuenta. Los códigos de escape (0F, 0F38, 0F3A) no cuentan.

Cuando busqué prefijos, fui golpeado con definiciones muy técnicas más allá de mis capacidades. O sugirió que estaban limitados a 4 por instrucción que entra en conflicto con el extracto anterior.

Entonces, en términos simples, ¿alguien puede explicar qué son / hacen y por qué es posible que desee agregar hasta 14+ en una instrucción en lugar de dividirla?


El trato de "cuatro prefijos" viene de los "grupos de prefijos":

  1. lock / rep / repne
  2. anulación de segmento
  3. anular el tamaño del operando
  4. anular el tamaño de la dirección

Puede repetir prefijos, pero no puede (puede, pero el comportamiento no está definido) usar varios prefijos diferentes del mismo grupo. Aunque eso solo se aplica a los grupos 1 y 2, los otros grupos tienen solo 1 cosa en cada uno.

Algo como 66 66 66 66 66 66 66 66 90 es válido (pero potencialmente lento de decodificar). 2E 3E 00 00 (anulaciones de segmentos de mezcla) no lo es.

Los prefijos de apilamiento pueden ser útiles para la alineación del código cuando los bytes deben ser ejecutados, a diferencia del relleno con nop , no cuesta tiempo de ejecución. Usar demasiados a la vez puede costarle tiempo a la decodificación.


Normalmente se usan tantas como se necesiten, con la instrucción deseada y los operandos que determinan eso. El ensamblador emite algunos de los prefijos de forma automática, mientras que otros los puedes usar manualmente.

El caso que mencionan es para NOP múltiples bytes que se usa tradicionalmente para el relleno de alineación donde la idea es usar una instrucción única pero apropiadamente larga para conservar los recursos. Aparentemente, usar más prefijos solo para mantener una sola instrucción puede ser peor que usar dos instrucciones con menos prefijos.

El recuento de prefijos de esta regla incluye el tamaño del operando, el tamaño de la dirección, el segmento, la repetición, el bloqueo, los prefijos REX y XOP. Un prefijo VEX de tres bytes cuenta como uno, mientras que un prefijo VEX de dos bytes no cuenta.

Ejemplos:

  • tamaño de operando: puede cambiar entre registros de 32 y 16 bits, por ejemplo mov ax, [foo] está codificado igual que mov eax, [foo] pero con el prefijo 66h
  • tamaño de dirección: puede cambiar entre tamaños de direcciones de 32/16 o 64/32 bits, por ejemplo, mov [eax], foo está codificado igual que mov [rax], foo pero con el prefijo 67h (en modo de 64 bits)
  • segmento: puede anular el segmento utilizado, por ejemplo, mov [fs:eax], foo se codifica igual que mov [eax], foo pero con el prefijo 64h .
  • repetición: se usa con instrucciones de cuerda para repetir, por ejemplo, rep cmpsb es el codificado igual que cmpsb pero con el prefijo f3h
  • lock: usado con ciertas instrucciones para hacer que sean atómicos, por ejemplo, lock add [foo], 1 está codificado igual que add [foo], 1 pero con el prefijo f0h
  • REX.W: se usa para cambiar al tamaño de operando de 64 bits, por ejemplo, add rax, 1 se codifica igual que add eax, 1 pero con el prefijo 48h
  • REX.R, B, X: se usa como extensiones del byte modr / m para acceder a los registros extra, por ejemplo, add r8d, 1 es lo mismo que add eax, 1 pero con el prefijo 41h
  • XOP, VEX: utilizado con subconjuntos de instrucciones vectoriales