Que signifie "rep; nop;" dans l'assemblage x86? Est-ce la même chose que l'instruction "pause"?
- que signifie
rep; nop
? - est-ce la même chose que
pause
instruction? - est-ce la même chose que
rep nop
(sans le semi-côlon)? - Quelle est la différence avec la simple instruction
nop
? - se comporte-t-il différemment sur les processeurs AMD et Intel?
- (bonus) où est la documentation officielle pour ces instructions?
Motivation pour cette question
après une discussion dans les commentaires de une autre question , j'ai réalisé que je ne sais pas ce que rep; nop;
signifie dans l'Assemblée 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 il l'était, dans l'ancien montage 16-bit x86). Selon ce tableau sommaire sur Wikipedia , il semble que rep
ne peut être utilisé qu'avec movs
, stos
, cmps
, lods
, scas
(mais peut-être que cette limitation a été supprimée sur les nouveaux processeurs). Ainsi, je pense que rep nop
(sans semi-côlon) répéterait une nop
opération cx
fois.
cependant, après une recherche plus approfondie, Je suis encore plus confus. Il semble que rep; nop
et pause
correspondent exactement au même opcode , et pause
a un comportement légèrement différent de juste nop
. Certains Vieux courrier de 2005 dit des choses différentes:
- "essayez de ne pas brûler trop de puissance "
- "c'est l'équivalent de" nop " juste avec 2 codage octet."
- "c'est de la magie sur intel. C'est comme 'nop mais laissez l'autre frère courir HT' "
- "c'est la pause sur les processeurs intel et rapide rembourrage sur les Athlon"
avec ces différentes opinions, Je ne pouvais pas comprendre le sens correct.
il est utilisé dans le noyau Linux (à la fois sur i386 et x86_64 ), avec ce commentaire: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
il est également étant utilisé dans BeRTOS , avec le même commentaire.
2 réponses
rep; nop
est en effet identique à l'instruction pause
(opcode F390
). Il pourrait être utilisé pour les monteurs qui ne supportent pas encore l'instruction pause
. Sur les processeurs précédents, cela n'a tout simplement rien fait, tout comme nop
mais en deux octets. Sur les nouveaux processeurs qui prennent en charge l'hyperthreading, il est utilisé pour indiquer au processeur que vous exécutez un spinloop pour augmenter les performances. De référence d'instruction Intel :
améliore les performances des boucles spin-wait. Lors de l'exécution d'une "boucle spin-wait", un processeur Pentium 4 ou Intel Xeon subit une sévère pénalité de performance lors de la sortie de la boucle parce qu'il détecte une violation possible de l'ordre de mémoire. L'instruction PAUSE indique au processeur que la séquence de code est une boucle spin-wait. Le processeur utilise cette indication pour éviter la violation de l'ordre de mémoire dans la plupart des situations, ce qui améliore considérablement le processeur performance. Pour cette raison, il est recommandé de placer une instruction PAUSE dans toutes les boucles spin-wait.
qui ne s'appliquent pas à une instruction sont ignorés. Cependant, les CPU futurs peuvent utiliser cette séquence d'octets pour encoder une nouvelle instruction. (Oui, l'espace opcode x86 est tellement limité qu'ils font des choses folles comme ça, et oui cela rend les décodeurs compliqués.)
dans ce cas, cela signifie que vous pouvez utiliser pause
en spinloops sans briser le compat à rebours . Les vieux CPU qui ne connaissent pas pause
vont le décoder comme un NOP pas de dégâts. Sur les nouveaux CPU, vous bénéficiez d'une économie d'énergie / convivialité HT, et de "éviter les fausses spéculations de commande de mémoire lorsque la mémoire sur laquelle vous tournez change et que vous quittez la boucle de spin.
liens vers les manuels D'Intel et des tonnes d'autres bonnes choses sur la page d'information wiki de la balise x86: https://stackoverflow.com/tags/x86/info
un autre cas de préfixe sans signification rep
devenant une nouvelle instruction sur les nouveaux CPU: lzcnt
est F3 0F BD /r
. Sur les CPU qui ne supportent pas cette instruction (manquant le drapeau de fonctionnalité LZCNT dans leur CPUID), il décode comme rep bsr
, qui court le même que bsr
. Donc sur les vieux CPU, il produit 32 - expected_result
, et n'est pas défini quand l'entrée était zéro.
Un cas d'un vide de sens rep
préfixe qui ne sera probablement jamais décoder autrement dit: rep ret
est utilisé par défaut par gcc lorsqu'il cible des CPU" génériques "(c.-à-d. qui ne ciblent pas un CPU spécifique avec -march
ou -mtune
, et qui ne ciblent pas AMD K8 ou K10. Il faudra des décennies avant que quelqu'un puisse faire un CPU qui décode rep ret
comme n'importe quoi d'autre que ret
, parce qu'il est présent dans la plupart des binaires dans la plupart des distributions Linux. Voir que signifie "représenter"?