¿Qué significa "rep; nop;" en el ensamblaje x86? ¿Es lo mismo que la instrucción de "pausa"?


  • ¿Qué significa rep; nop?
  • ¿Es lo mismo que pause la instrucción?
  • ¿Es lo mismo que rep nop (sin el punto y coma)?
  • ¿Cuál es la diferencia con la instrucción simple nop?
  • ¿Se comporta de manera diferente en los procesadores AMD e Intel?
  • (bonus) ¿Dónde está la documentación oficial para estas instrucciones?

Motivación para esta pregunta

Después de alguna discusión en los comentarios de otro pregunta , me di cuenta de que no se lo que rep; nop; significa en el ensamblaje x86 (o x86-64). Y tampoco pude encontrar una buena explicación en la web.

Sé que rep es un prefijo que significa "repetir la siguiente instrucción cx veces" (o al menos lo era, en el antiguo ensamblado x86 de 16 bits). De acuerdo con esta tabla de resumen en Wikipedia , parece que rep solo se puede usar con movs, stos, cmps, lods, scas (pero tal vez esta limitación se eliminó en los procesadores más nuevos). Por lo tanto, yo pensaría que rep nop (sin punto y coma) repetiría una operación nop cx veces.

Sin embargo, después de buscar más, me confundí aún más. Parece que rep; nop y pause mapea exactamente el mismo opcode , y pause tiene un comportamiento un poco diferente que solo nop. Algunos correos antiguos de 2005 decían cosas diferentes: {[41]]}

  • "trate de no quemar demasiado poder"
  • "es equivalente a' nop ' solo con 2 bytes codificación."
  • "es magia en inteligencia. Es como 'nop pero deja que el otro hermano de HT corra'"
  • "es una pausa en intel y un relleno rápido en Athlon"

Con estas diferentes opiniones, no podía entender el significado correcto.

Se está utilizando en el núcleo Linux (tanto en i386 y x86_64), junto con este comentario: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ También se está utilizando en BeRTOS, con el mismo comentario.

Author: Flow, 2011-08-17

2 answers

rep; nop es de hecho lo mismo que la instrucción pause (opcode F390). Podría usarse para ensambladores que aún no soportan la instrucción pause. En procesadores anteriores, esto simplemente no hacía nada, al igual que nop pero en dos bytes. En los nuevos procesadores que admiten hyperthreading, se usa como una pista al procesador de que está ejecutando un spinloop para aumentar el rendimiento. De Referencia de instrucciones de Intel :

Mejora el rendimiento de los bucles spin-wait. Cuando al ejecutar un "bucle spin-wait", un procesador Pentium 4 o Intel Xeon sufre una grave penalización de rendimiento al salir del bucle porque detecta una posible violación del orden de memoria. La instrucción PAUSE proporciona una pista al procesador de que la secuencia de código es un bucle spin-wait. El procesador utiliza esta sugerencia para evitar la violación del orden de la memoria en la mayoría de las situaciones, lo que mejora en gran medida el rendimiento del procesador. Por esta razón, se recomienda que se coloque una instrucción de PAUSA en todos los spin-wait bucle.

 65
Author: ughoavgfhw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-08 10:07:10

Los prefijos que no se aplican a una instrucción son ignorados. Sin embargo, las CPU futuras pueden usar esa secuencia de bytes para codificar una nueva instrucción. (sí, el espacio del opcode x86 es tan limitado que hacen cosas locas como esta, y sí, hace que los decodificadores sean complicados.)

En este caso, significa que puede usar pause en spinloops sin romper hacia atrás compat. Las CPU antiguas que no conocen pause lo decodificarán como un NOP sin daño. En las nuevas CPU, obtienes el beneficio de ahorro de energía / compatibilidad con HT, y evitar la especulación errónea de ordenar la memoria cuando la memoria en la que estás girando cambia y estás dejando el bucle de giro.


Enlaces a los manuales de Intel y toneladas de otras cosas buenas en la página de información wiki de etiquetas x86: https://stackoverflow.com/tags/x86/info

Otro caso de un prefijo sin sentido rep convirtiéndose en una nueva instrucción en nuevas CPU: lzcnt es F3 0F BD /r. En CPU que no soportan esa instrucción (falta el LZCNT feature flag en su CPUID), se decodifica como rep bsr, que se ejecuta igual que bsr. Así que en CPU antiguas, produce 32 - expected_result, y es indefinido cuando la entrada era cero.


Un caso de un prefijo rep sin sentido que probablemente nunca decodificará de manera diferente: rep ret es utilizado por defecto por gcc cuando se dirige a CPU "genéricas" (es decir, no se dirige a una CPU específica con -march o -mtune, y no se dirige a AMD K8 o K10.) Pasarán décadas antes de que alguien pueda hacer una CPU que decodifique rep ret como cualquier otra cosa que no sea ret, porque está presente en la mayoría de los binarios en la mayoría de las distribuciones de Linux. Ver ¿Qué significa `rep ret`?

 7
Author: Peter Cordes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-17 18:51:58