web-dev-qa-db-fra.com

Que signifie "rep; nop;" signifie dans l'assemblage x86? Est-ce la même que l'instruction "pause"?

  • Que signifie rep; nop?
  • Est-ce la même que l'instruction pause?
  • Est-ce la même chose que rep nop (Sans le point-virgule)?
  • Quelle est la différence avec la simple instruction nop?
  • Se comporte-t-il différemment sur les processeurs AMD et Intel?
  • (bonus) Où se trouve la documentation officielle de ces instructions?

Motivation pour cette question

Après une discussion dans les commentaires de ne autre question , j'ai réalisé que je ne sais pas ce que rep; nop; Signifie dans l'assemblage x86 (ou x86-64). Et aussi je n'ai pas pu trouver une bonne explication sur le web.

Je sais que rep est un préfixe qui signifie "répéter l'instruction suivante cx fois" (ou du moins était, dans l'ancien assemblage x86 16 bits). D'après cela tableau récapitulatif sur Wikipedia , il semble que rep ne peut être utilisé qu'avec movs, stos, cmps, lods, scas (mais cette limitation a peut-être été supprimée sur les nouveaux processeurs). Ainsi, je penserais que rep nop (Sans point-virgule) répéterait une opération nopcx fois.

Cependant, après de nouvelles recherches, je suis devenu encore plus confus. Il semble que rep; nop Et pausemappent exactement au même opcode , et pause a un comportement un peu différent que simplement nop . Certains ancien courrier de 2005 ont dit des choses différentes:

  • "essayez de ne pas brûler trop d'énergie"
  • "c'est équivalent à 'nop' juste avec un codage sur 2 octets."
  • "c'est magique sur Intel. C'est comme 'nop mais laissez l'autre frère HT courir'"
  • "c'est une pause sur Intel et un remplissage rapide sur Athlon"

Avec ces différentes opinions, je ne pouvais pas comprendre le sens correct.

Il est utilisé dans le noyau Linux (sur les deux i386 et x86_64 ), avec ce commentaire: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ Il est également tilisé dans BeRTOS , avec le même commentaire.

76
Denilson Sá Maia

rep; nop est en effet la même que l'instruction pause (opcode F390). Il peut être utilisé pour les assembleurs qui ne prennent pas encore en charge l'instruction pause. Sur les processeurs précédents, cela ne faisait tout simplement rien, tout comme nop mais en deux octets. Sur les nouveaux processeurs prenant en charge l'hyperthreading, il est utilisé pour indiquer au processeur que vous exécutez une boucle tournante pour augmenter les performances. De référence d'instructions d'Intel :

Améliore les performances des boucles d'attente d'attente. Lors de l'exécution d'une "boucle d'attente de rotation", un processeur Pentium 4 ou Intel Xeon subit une grave pénalité de performances à la sortie de la boucle car il détecte une violation possible de l'ordre de la mémoire. L'instruction PAUSE indique au processeur que la séquence de code est une boucle d'attente d'attente. Le processeur utilise cette astuce pour éviter la violation de l'ordre de la mémoire dans la plupart des situations, ce qui améliore considérablement les performances du processeur. Pour cette raison, il est recommandé de placer une instruction PAUSE dans toutes les boucles d'attente d'attente.

66
ughoavgfhw

Les préfixes qui ne s'appliquent pas à une instruction sont ignorés. Cependant, les futurs processeurs peuvent utiliser cette séquence d'octets pour coder une nouvelle instruction. (oui, l'espace d'opcode x86 est si limité qu'ils font des trucs fous comme ça, et oui cela complique les décodeurs.)

Dans ce cas, cela signifie que vous pouvez utiliser pause dans les boucles de spin sans casser la compatibilité arrière . Les anciens processeurs qui ne connaissent pas pause le décoderont comme un NOP sans aucun dommage. Sur les nouveaux processeurs, vous bénéficiez d'une économie d'énergie/convivialité HT, et évitant les spéculations erronées dans l'ordre de la mémoire lorsque la mémoire sur laquelle vous tournez change et que vous quittez la boucle de rotation.


Liens vers les manuels d'Intel et des tonnes d'autres bonnes choses sur la page d'informations wiki de la balise x86: https://stackoverflow.com/tags/x86/info

Un autre cas où un préfixe rep vide de sens devient une nouvelle instruction sur les nouveaux processeurs: lzcnt est F3 0F BD /r. Sur les processeurs qui ne prennent pas en charge cette instruction (il manque l'indicateur de fonctionnalité LZCNT dans leur CPUID), il décode comme rep bsr, qui fonctionne de la même manière que bsr. Ainsi, sur les anciens processeurs, il produit 32 - expected_result, et n'est pas défini lorsque l'entrée était nulle.


Un cas d'un préfixe rep vide de sens qui ne décodera probablement jamais différemment: rep ret est utilisé par défaut par gcc lors du ciblage de CPU "génériques" (c'est-à-dire sans cibler un CPU spécifique avec -march ou -mtune, et sans viser AMD K8 ou K10.) Il faudra des décennies avant que quiconque puisse créer un processeur qui décode rep ret comme autre chose que ret, car il est présent dans la plupart des binaires de la plupart des distributions Linux. Voir Que signifie "rep ret"?

9
Peter Cordes