Pourquoi la rbp et la rsp appelés registres?

selon Intel dans x64 les registres suivants sont appelés registres à usage général (RAX, RBX, RCX, RDX, RBP, RSI, RDI, RSP et R8-R15) https://software.intel.com/en-us/articles/introduction-to-x64-assembly.

dans l'article suivant, il est écrit que RBP et RSP sont des registres spéciaux (point RBP à la base du cadre de la pile actuelle et point RSP au sommet de la pile actuelle cadre.) https://www.recurse.com/blog/7-understanding-c-by-learning-assembly

maintenant j'ai deux affirmations contradictoires. La déclaration Intel devrait être celle qui est fiable, mais qu'est-ce qui est correct et pourquoi la RBP et la RSP sont appelés à des fins générales du tout ?

merci de votre aide.

8
demandé sur duskwuff 2016-04-10 15:02:21

2 réponses

usage général signifie que tous ces registres peuvent être utilisés avec n'importe quelles instructions faisant le calcul avec des registres à usage général tandis que, par exemple, vous ne pouvez pas faire ce que vous voulez avec le pointeur d'instruction (RIP) ou le registre de drapeaux (RFLAGS).

certains de ces registres ont été conçus pour être utilisés à des fins précises, et le sont couramment. Les plus critiques sont la RSP et la RBP.

si vous avez besoin de les utiliser pour votre propre usage, vous devez enregistrer leur contenu avant de stocker quelque chose d'autre à l'intérieur, et les restaurer à leur valeur originale une fois fait.

11
répondu jlliagre 2017-07-30 08:23:41

Si un registre peut être un opérande add, ou utilisé dans un mode d'adressage, c'est "généraliste", par opposition aux registres comme le FS registre de segment, ou RIP. Les registres GP sont aussi appelés "registres entiers", même si d'autres types de registres peuvent contenir des entiers, aussi.

dans l'architecture informatique, il est courant pour les CPU de traiter en interne des registres / instructions entiers séparément des registres/instructions FP / SIMD. par exemple Intel Sandybridge-famille de Processeurs ont des fichiers de registres physiques séparés pour renommer les registres GP integer vs. FP/vector. Ceux-ci sont simplement appelés les dossiers de registre integer vs. FP. (Où FP est un raccourci pour tout ce qu'un noyau n'a pas besoin de sauvegarder/restaurer pour utiliser les registres GP tout en laissant intact L'état FPU/SIMD de l'espace utilisateur.) Chaque entrée dans le fichier de registre FP est de 256 bits de large( pour contenir un vecteur AVX ymm), mais les entrées de fichier de registre entier seulement doivent être 64 bits large.

sur les CPU qui renomment les registres de segments ( Skylake ne fait pas), je suppose que cela ferait partie de l'état entier, et donc RFLAGS + RIP. Mais quand nous disons "registre entier", nous voulons normalement dire spécifiquement un registre universel.


chaque registre a quelques particularités pour certaines instructions, à l'exception de quelques registres complètement nouveaux ajoutés avec x86-64: R8-R15. Ils ne les disqualifient pas en tant que Généraux. But La (faible 16 de la) 8 date de retour à 8086, et il y avait des utilisations implicites de chacun d'entre eux, même dans l'original 8086.

pour RSP, c'est spécial pour push/pop/call/ret, donc la plupart du code ne l'utilise jamais pour autre chose. (Et en mode noyau, utilisé asynchrone pour les interruptions, donc vous ne pouvez vraiment pas le cacher quelque part pour obtenir un registre GP supplémentaire de la façon dont vous pouvez dans le code de l'espace utilisateur: le PSR est-il aussi universel que le EAX?)

mais en controlled conditional (comme no signal handlers) vous n'avez pas besoin d'utiliser RSP pour un pointeur de pile. par exemple, vous pouvez l'utiliser pour lire un tableau dans une boucle avec de la pop, comme dans ce code-Réponse de golf. (J'ai utilisé esp EN Code 32 bits, mais même différence:pop est plus rapide que lodsd sur Skylake, alors que les deux sont de 1 byte.)


utilisations implicites et particularités de chaque registre:

Voir aussi x86 Assemblée - Pourquoi est [e]bx conservé dans les conventions d'appel? pour une liste partielle.

Je limite principalement cela aux instructions de l'espace utilisateur, surtout celles qu'un compilateur moderne pourrait en fait émettre à partir du code C ou c++. Je n'essaie pas d'être exhaustif pour les règlements qui ont beaucoup d'utilisations implicites.

  • rax: opérande [i]mul / [i]div / cdq / cdqe, instructions de chaîne (stos), cmpxchg, etc. etc. Ainsi que des encodages Spéciaux plus courts pour de nombreuses instructions, comme xchg-avec-eax qui est où 0x90 nop provenait de (avant qu'il ne devienne une instruction séparée dans x86-64, parce que xchg eax,eax zero-étend eax dans RAX et ne peut donc pas utiliser le 0x90 l'encodage. Mais xchg rax,rax peut encore s'assembler à REX.W=1 0x90.
  • rcx: maj compte, repchaîne compte, le lent loop l'instruction
  • rdx:rdx:rax est utilisé par diviser et multiplier, et cwd / cdq / cqo pour les configurer. rdtsc. BMI2 mulx.
  • rbx: 8086 xlatb. cpuid utilisez les quatre EAX..EDX. 486 cmpxchg8b, x86-64 cmpxchg16b. Les compilateurs émettront cmpxchg8std::atomic<long long>::compare_exchange_weak, et 16b pour atomic<struct_16_bytes>. RBX a le moins d'utilisations implicites des 8 originaux, mais lock cmpxchg16b est l'un des rares compilateurs utilisent réellement.
  • rsi/rdi: chaîne de caractères de la fpo, y compris rep movsb que certains compilateurs utilisent parfois. (gcc aussi inlines rep cmpsb pour les littéraux de chaîne, dans certains cas, mais ce n'est probablement pas optimale).
  • rbp:leave (seulement 1 uop plus lent que mov rsp, rbp/pop rbp. gcc l'utilise réellement dans des fonctions avec un pointeur de cadre, quand il ne peut pas juste pop rbp). Aussi horriblement lent enter que personne n'utilise jamais.
  • rsp: pile ops: push/pop / appel/reg, et leave. (Et enter).

  • r11:syscall/sysret l'utiliser pour enregistrer / restaurer les RFLAGS de l'espace utilisateur. (Avec RCX pour sauvegarder / restaurer le RIP de l'espace utilisateur).

encodage en mode adressage cas particuliers:

rbp/r13 ne peut pas être un registre de base sans déplacement: codage au lieu de cela signifie: (en ModRM) rel32 RIP (relatif), ou (en SIB) disp32 sans registre de base. (r13 utilise les mêmes 3 bits dans ModRM / SIB, donc ce choix simplifie le décodage en ne faisant pas la longueur d'instruction décodeur regardez le REX.B bit pour obtenir le 4ième bit de base-register). [r13] assemble [r13 + disp8=0]. [r13+rdx] assemble [rdx+r13] (éviter le problème en changeant la base/l'index lorsque c'est une option).

rsp/r12 en tant que base, le registre a toujours besoin d'un octet. (L'encodage ModR/M de base=RSP est un code d'échappement pour signaler un octet SIB, Et encore une fois, plus de décodeur devrait se soucier du préfixe REX si r12 a été traitée différemment.)

rsp ne peut pas être un indice de registre. Cela permet de coder [rsp], qui est plus utile que [rsp + rsp]. (Intel aurait pu concevoir les encodages ModRM/SIB pour les modes d'adressage 32 bits (nouveau en 386), de sorte que le SIB-with-no-index n'était possible qu'avec base=ESP. Que ferait [eax + esp*4] possible et seulement exclure [esp + esp*1/2/4/8]. Mais ce n'est pas utile, donc ils ont simplifié le matériel en faisant index = ESP le code pour no index indépendamment de la base. Cela permet deux méthodes redondantes pour encoder n'importe quel mode d'adressage base ou base+disp: avec ou sans SIB.)

r12 être un indice inscrire. Contrairement aux autres cas, cela n'affecte pas le décodage de la longueur d'instruction. En outre, il ne peut pas être travaillé avec un encodage plus long comme les autres cas. AMD voulait que le registre D'AMD64 soit aussi orthogonal que possible, donc c'est logique qu'ils aient dépensé quelques transistors supplémentaires pour vérifier REX.X as une partie de l'index / indice de décodage. Par exemple, [rsp + r12*4] nécessite des index=r12, afin d'avoir r12 pas tout à fait généralement objectif ferait AMD64 une cible de compilateur pire.

   0:   41 8b 03                mov    eax,DWORD PTR [r11]
   3:   41 8b 04 24             mov    eax,DWORD PTR [r12]      # needs a SIB like RSP
   7:   41 8b 45 00             mov    eax,DWORD PTR [r13+0x0]  # needs a disp8 like RBP
   b:   41 8b 06                mov    eax,DWORD PTR [r14]
   e:   41 8b 07                mov    eax,DWORD PTR [r15]
  11:   43 8b 04 e3             mov    eax,DWORD PTR [r11+r12*8] # *can* be an index

compilateurs aiment quand tous les registres être utilisé pour n'importe quoi, seulement limiter l'allocation de Registre pour quelques opérations spéciales. C'est ce qu'on entend par orthogonalité de registre.

2
répondu Peter Cordes 2018-07-15 10:01:02