web-dev-qa-db-fra.com

Le point de test% eax% eax

Duplicate possible:
Assemblée x86 - 'testl ’eax contre eax?

Je suis très nouveau dans la programmation en langage d'assemblage et j'essaie actuellement de lire le langage d'assemblage généré à partir d'un fichier binaire. J'ai croisé

 test   %eax,%eax

ou test %rdi, %rdi, etc. etc. Je suis très confus quant à son utilisation. Les valeurs dans %eax, %eax ne sont-elles pas les mêmes? Qu'est-ce qu'il teste? J'ai lu quelque part qu'il effectue l'opération AND ..... mais puisqu'elles ont la même valeur, ne renverrait-il pas simplement %eax?

Ce qui suit est juste un exemple où j'ai trouvé cette utilisation:

   400e6e:       85 c0                   test   %eax,%eax
   400e70:       74 05                   je     400e77 <phase_1+0x23>

Je pensais que je saute si les deux valeurs comparées sont égales ...... eh bien, parce que %eax est bien, lui-même, dans quelle situation ne sauterions-nous pas?

Je suis un débutant en programmation en général, donc je l'apprécierais beaucoup si quelqu'un pouvait m'expliquer cela. Merci!

116
pauliwago

CMP soustrait les opérandes et définit les drapeaux. À savoir, il active l'indicateur zéro si la différence est égale à zéro (les opérandes sont égaux).

TEST définit l'indicateur de zéro, ZF, lorsque le résultat de l'opération AND est égal à zéro. Si deux opérandes sont égaux, leur ET au niveau du bit est nul quand les deux sont nuls. TEST définit également l'indicateur de signe, SF, lorsque le bit le plus significatif est défini dans le résultat, et l'indicateur de parité, PF, lorsque le nombre de bits définis est pair.

JE [Saut si égal] teste l'indicateur de zéro et saute si l'indicateur est défini. JE est un alias de JZ [Jump if Zero] afin que le désassembleur ne puisse pas en sélectionner un en fonction de l'opcode. JE est nommé tel parce que l'indicateur zéro est défini si les arguments de CMP sont égaux.

Alors,

TEST %eax, %eax
JE   400e77 <phase_1+0x23>

saute si le %eax est égal à zéro.

134
John Dvorak

Certaines instructions x86 sont conçues pour laisser le contenu des opérandes (registres) en l’état et simplement pour activer/désactiver des indicateurs de CPU internes spécifiques, tels que l’indicateur zéro (ZF). Vous pouvez considérer le ZF comme un indicateur booléen vrai/faux qui réside dans la CPU.

dans ce cas particulier, l’instruction TEST exécute un ET logique au niveau des bits, ignore le résultat réel et active/désactive le ZF en fonction du résultat du logique et: si le résultat est nul, elle définit ZF = 1, sinon définit ZF = 0.

Les instructions de saut conditionnel telles que JE sont conçues pour examiner le ZF en sautant/ne sautant pas; utiliser TEST et JE ensemble revient donc à effectuer un saut conditionnel en fonction de la valeur d'un registre spécifique:

exemple:

TEST EAX, EAX
JE une_adresse

la CPU passera à "adresse_certain" si et seulement si ZF = 1, autrement dit si et seulement si AND (EAX, EAX) = 0, ce qui peut se produire si et seulement si EAX == 0

le code C équivalent est:

if(eax == 0)
{
    goto some_address
}
46
Gianluca Ghettini

Ceci vérifie si EAX est zéro. L'instruction test effectue au niveau du bit AND entre les arguments, et si EAX contient zéro, le résultat définit le facteur ZF ou ZeroFlag.

12
ppeterka

Vous avez raison, cette test "et" s les deux opérandes. Mais le résultat est jeté, la seule chose qui reste, et c'est la partie importante, ce sont les drapeaux. Ils sont définis et c’est la raison pour laquelle l’instruction test est utilisée (et existe).

JE ne saute pas lorsqu'il est égal (il a le sens quand l'instruction précédente était une comparaison), mais ce qu'il fait réellement, il saute quand le drapeau ZF est activé. Et comme il s’agit de l’un des drapeaux définis par test, cette séquence d’instructions (test x, x; je ...) signifie qu’elle est sautée lorsque x vaut 0.

Pour des questions comme celle-ci (et pour plus de détails), je ne peux que recommander un livre sur l’instruction x86, par exemple. même quand c'est vraiment gros, la documentation d'Intel est très bonne et précise.

4
flolo

test est un and non destructif, il ne renvoie pas le résultat de l'opération, mais définit le registre d'indicateurs en conséquence. Pour savoir ce qu’il teste réellement, vous devez vérifier les instructions suivantes. Souvent, out est utilisé pour vérifier un registre par rapport à 0, éventuellement associé à un saut conditionnel jz.

3
Jens Björnhager