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 :))
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
où 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.
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.
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.
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.
Réponses:
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
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.
la source
SI
= Index sourceDI
= Index de destinationComme 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
ES
registre de segment doit être utilisé avecDI
etDS
avecSI
comme dansSI et DI peuvent également être utilisés comme registres d'index à usage général. Par exemple, le
C
code sourcese compile en
où
ebp+12
contientargv
,ebx
estj
etedi
asrcidx
. Notez que la troisième instruction utiliseedi
multiplié par 4 et ajoute unebp
décalage de 0x54 (l'emplacement desrcp
); 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
= accumulateurDX
= double mot accumulateurCX
= compteurBX
= registre de baseIls 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.
la source
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,
la source
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 AVXVMASKMOVDQU
) écrit sélectivement les octets d'un registre XMM vers la mémoire pointée par EDI / RDI.la source
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.
la source