Question

Dans le code assembleur suivant que je jetai à l'aide objdump:

lea    0x0(%esi,%eiz,1),%esi

Qu'est-ce que %eiz de registre? Qu'est-ce que le code précédent signifie?

Était-ce utile?

La solution

Voir Pourquoi Est-ce que GCC LEA EIZ :

  

Apparemment %eiz est un pseudo-registre qui vient valeur zéro en tout temps (comme r0 sur MIPS).

...

  

J'ai finalement trouvé une liste de diffusion après par le gourou binutils Ian Lance Taylor qui révèle la réponse. Parfois, insère GCC NOP dans le flux de code pour assurer un bon alignement et d'autres choses comme ça. L'instruction NOP prend un octet, donc on pourrait penser que vous pourriez simplement ajouter autant que nécessaire. Mais selon Ian Lance Taylor, il est plus rapide pour la puce pour exécuter une instruction longue que de nombreuses instructions courtes. Ainsi, plutôt que d'insérer sept NOP, ils utilisent à la place une LEA Bizarro, qui utilise jusqu'à sept octets et est sémantiquement équivalent à un NOP.

Autres conseils

(très tard pour le jeu, mais cela semblait être un ajout intéressant): Ce n'est pas un registre du tout, il est une bizarrerie de l'encodage d'instructions Intel. Lors de l'utilisation d'un octet ModRM à charger à partir de la mémoire, il y a 3 bits utilisés pour le champ de registre pour stocker les 8 entrées possibles. Mais l'endroit où l'ESP (le pointeur de la pile) « serait » au lieu est interprété par le processeur comme « un octet SIB suit cette instruction » (à savoir qu'il est un mode d'adressage étendu, et non une référence à ESP). Pour des raisons connues seulement les auteurs, l'assembleur GNU a toujours représenté ce « zéro où un registre serait autrement » comme un registre « % EIz ». La syntaxe Intel laisse tomber juste.

Andy Ross fournit beaucoup plus du raisonnement sous-jacent, mais est malheureusement mal ou à tout le moins confus au sujet des détails techniques. Il est vrai qu'une adresse efficace de tout (%esp) ne peut pas être codé avec juste l'octet ModR / M comme au lieu d'être décodé comme (%esp), il est utilisé pour signaler qu'un octet SIB est également inclus. Cependant, le pseudo-registre %eiz est pas toujours utilisé avec un octet SIB pour représenter qu'un octet SIB a été utilisé.

L'octet SIB (échelle / index / base) a trois pièces à cela: l'index (un registre tel que comme %eax ou %ecx que l'échelle est appliquée à), l'échelle (une puissance de deux de 1 à 8 qui le registre d'index est multiplié par), et la base (un autre registre qui est ajouté à l'index mis à l'échelle). C'est ce qui permet des instructions telles que add %al,(%ebx,%ecx,2) (code machine: 00 04 4b - opcode, MODR / m, sib (notez pas% EIz registre même si l'octet SIB a été utilisé)) (ou dans la syntaxe Intel, « ajouter BYTE PTR [ecx * 2 + EBX], al ").

Cependant, %esp ne peut pas être utilisé comme registre d'index dans un octet SIB. Au lieu de laisser cette option, Intel ajoute plutôt une option pour utiliser le registre de base comme il est sans mise à l'échelle ou l'indexation. Par conséquent, pour lever l'ambiguïté entre le cas de add %al,(%ecx) (code machine: 00 01 - opcode, MODR / m) et add %al,(%ecx) (code machine: 00 04 21 - opcode, MODR / m, sib), la syntaxe alternative add %al,(%ecx,%eiz,1) est utilisé à la place (ou pour Intel syntaxe:. add BYTE PTR [ecx+eiz*1],al)

Et comme expliqué dans l'article lié par Sinan, cette instruction spécifique (lea 0x0(%esi,%eiz,1),%esi) est simplement utilisé comme un nop multi-octets (ce qui équivaut à esi = &*esi) de sorte que seulement une instruction de type NOP doit être exécutée à la place de multiples nop instructions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top