Objectif des registres ESI et EDI?


Réponses:


77

Il y a quelques opérations que vous pouvez seulement faire avec DI / SI (ou leurs homologues étendus, si vous ne l' avez pas appris ASM en 1985). Parmi ceux-ci sont

REP STOSB
REP MOVSB
REP SCASB

Qui sont, respectivement, des opérations de stockage, de chargement et de balayage répétés (= massifs). Ce que vous faites est de configurer SI et / ou DI pour pointer sur un ou les deux opérandes, peut-être mettre un compte dans CX et laisser ensuite déchirer. Ce sont des opérations qui fonctionnent sur un tas d'octets à la fois, et elles mettent en quelque sorte le processeur en mode automatique. Parce que vous ne codez pas explicitement les boucles, elles font leur travail plus efficacement (généralement) qu'une boucle codée à la main.

Juste au cas où vous vous poseriez la question: selon la façon dont vous configurez l'opération, le stockage répété peut être quelque chose de simple comme poinçonner la valeur 0 dans un grand bloc de mémoire contigu; MOVSB ​​est utilisé, je pense, pour copier des données d'un tampon (enfin, n'importe quel tas d'octets) vers un autre; et SCASB est utilisé pour rechercher un octet qui correspond à un critère de recherche (je ne sais pas s'il s'agit uniquement d'une recherche d'égalité, ou quoi - vous pouvez le rechercher :))

C'est à cela que servent ces règlements.


7
Conseil d'optimisation du passé: rep stosw est beaucoup plus rapide que rep stosb , donc si la copie de deux et deux octets correspond à ce que vous essayez de faire, utilisez-la à la place dans votre code d'assemblage x86 16 bits optimisé à la main ...
Alexander

88

SI= Index source
DI= Index de destination

Comme d'autres l'ont indiqué, ils ont des utilisations spéciales avec les instructions de chaîne. Pour la programmation en mode réel, le ESregistre de segment doit être utilisé avec DIet DSavec SIcomme dans

movsb  es:di, ds:si

SI et DI peuvent également être utilisés comme registres d'index à usage général. Par exemple, le Ccode source

srcp [srcidx++] = argv [j];

se compile en

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi

ebp+12contient argv, ebxest jet edia srcidx. Notez que la troisième instruction utilise edimultiplié par 4 et ajoute un ebpdécalage de 0x54 (l'emplacement de srcp); les parenthèses autour de l'adresse indiquent l'indirection.


Bien que je ne me souvienne pas où je l'ai vu, mais cela le confirme en grande partie, et ceci (diapositive 17) d'autres:

AX= accumulateur
DX= double mot accumulateur
CX= compteur
BX= registre de base

Ils ressemblent à des registres à usage général, mais il existe un certain nombre d'instructions qui (de façon inattendue?) Utilisent l'une d'entre elles - mais laquelle? - de manière implicite.


37

Des opcodes comme MOVSB ​​et MOVSW qui copient efficacement les données de la mémoire pointée par ESI vers la mémoire pointée par EDI. Donc,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!

12

En plus des opérations de chaîne (MOVS / INS / STOS / CMPS / SCASB / W / D / Q etc.) mentionnées dans les autres réponses, je voulais ajouter qu'il existe également des instructions d'assemblage x86 plus «modernes» qui utilisent implicitement à moins EDI / RDI:

L' instruction SSE2 MASKMOVDQU(et la prochaine AVX VMASKMOVDQU) écrit sélectivement les octets d'un registre XMM vers la mémoire pointée par EDI / RDI.


6

En plus des registres utilisés pour les opérations de masse, ils sont utiles pour leur propriété d'être préservés par un appel de fonction (appel préservé) dans la convention d'appel 32 bits. Les ESI, EDI, EBX, EBP, ESP sont préservés des appels tandis que EAX, ECX et EDX ne sont pas préservés des appels. Les registres préservés des appels sont respectés par la fonction de bibliothèque C et leurs valeurs persistent lors des appels de fonction de bibliothèque C.

Jeff Duntemann dans son livre de langage d'assemblage a un exemple de code d'assemblage pour imprimer les arguments de ligne de commande. Le code utilise esi et edi pour stocker les compteurs car ils ne seront pas modifiés par la fonction de bibliothèque C printf. Pour les autres registres comme eax, ecx, edx, il n'y a aucune garantie qu'ils ne soient pas utilisés par les fonctions de la bibliothèque C.

https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025

See section 12.8 Comment C voit les arguments de ligne de commande.

Notez que les conventions d'appel 64 bits sont différentes des conventions d'appel 32 bits, et je ne sais pas si ces registres sont préservés ou non.


Je n'ai jamais entendu parler de «sacré» pour décrire ce que la plupart des gens appellent «volatile» / «non volatile», ou «sauvé par l'appelé» ou «sauvé par l'appelant». J'aime "call-préservé" / "call-clobbered", car cela n'implique pas qu'ils sont enregistrés n'importe où. Quoi qu'il en soit, ESI / RSI et EDI / RDI ne sont pas préservés des appels dans l'ABI x86-64 System V.
Peter Cordes

De plus, vous avez oublié de lister EBP et ESP comme étant des appels préservés dans les conventions d'appel 32 bits courantes.
Peter Cordes

1
Quoi qu'il en soit, c'est un très bon point. Dans le code réel, vous êtes plus susceptible de choisir EDI / ESI pour quelque chose basé sur des raisons de convention d'appel que parce qu'ils sont spéciaux pour les instructions.
Peter Cordes

J'aime les appels préservés. J'ai mis à jour la réponse avec la même chose. Merci pour l'examen.
Jay Rajput
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.