'testl' eax contre eax?

j'essaie de comprendre une assemblée.

l'assemblée comme suit, je m'intéresse à la ligne testl :

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

j'essaie de comprendre ce point de testl entre %eax et %eax ? Je pense que les détails de ce que ce code n'est pas important, j'essaie juste de comprendre le test avec lui - même-la valeur ne serait-elle pas toujours vraie?

104
demandé sur Michael Petch 2008-09-29 05:22:57

8 réponses

Il teste si eax est 0 ou au-dessus ou au-dessous. Dans ce cas, le saut est pris si eax est 0.

75
répondu Chris Jester-Young 2016-12-09 01:08:52

la signification de test est to et les arguments ensemble, et vérifier le résultat pour zéro. Donc ce code teste si EAX est zéro ou pas. je sautera si zéro.

BTW, cela génère une instruction plus petite que cmp eax, 0 qui est la raison pour laquelle les compilateurs vont généralement le faire de cette façon.

83
répondu phuclv 2017-04-28 03:57:08

l'instruction d'ESSAI fait une opération logique et-entre les opérandes, mais ne renvoie pas le résultat dans un registre. Seuls les drapeaux sont mis à jour.

dans votre exemple le test eax, eax définira le drapeau zéro si eax est zéro, le drapeau signe-si le bit le plus élevé est placé et quelques autres drapeaux aussi bien.

le saut si L'instruction Equal (je) saute si le drapeau Zéro est activé.

Vous pouvez traduire le code plus lisible code comme ceci:

cmp eax, 0
je  somewhere

qui a la même fonctionnalité mais nécessite quelques octets plus d'espace de code. C'est la raison pour laquelle le compilateur émet un test au lieu de comparer.

32
répondu Nils Pipenbrinck 2008-09-29 01:29:03

test est comme and , sauf qu'il n'écrit que des drapeaux, laissant ses deux entrées non modifiées. Avec deux entrées différentes , il est utile pour tester si certains bits sont tous zéro, ou si au moins un est défini. (par exemple test al, 3 définit ZF si EAX est un multiple de 4 (et a donc les deux de ses 2 bits Bas mis à zéro).


test eax,eax fixe tous les drapeaux exactement de la même manière que cmp eax, 0 voudrait :

  • FC et DES dégagée (ET/TEST toujours fait; et en soustrayant zéro ne produit jamais un report)
  • ZF, SF et PF selon la valeur en EAX. ( a = a&a = a-0 )

(à l'exception du drapeau obsolète AF (auxiliaire-carry flag, utilisé par les instructions ASCII/BCD). TEST laisse non défini , mais CMP le met" selon le résultat " . Puisque soustraire zéro ne peut pas produire un carry du 4ème au 5ème bit, CMP devrait toujours effacer AF).


TEST est plus petit (pas immédiat) et parfois plus rapide (peut macro-fusionner dans un UOP de comparaison et de branche sur plus de CPU dans plus de cas que CMP). qui fait de test l'idiome préféré pour tester un registre pour zéro ou pas .

la seule raison commune pour utiliser CMP avec un 0 immédiat est quand vous voulez comparer avec un opérande mémoire (par exemple, cmpb " 151970920 ", (%esi) pour vérifier un octet zéro terminal à la fin d'une chaîne de style C de longueur implicite).


AVX512F ajoute kortestw k1, k2 et AVX512DQ / BW (Skylake mais pas KNL) ajouter ktestb/w/d/q k1, k2 , qui fonctionnent sur les registres de masques AVX512 (k0..k7) mais toujours mettre des drapeaux réguliers comme test fait, de la même manière que l'entier OR ou AND instructions faire.

kortestw k1,k1 est le idiomatiques façon de direction / cmovcc / setcc basée sur une AVX512 comparer le résultat, en remplacement de l'ESS/AVX2 (v)pmovmskb/ps/pd + test ou cmp .


L'utilisation de jz vs. je peut être déroutant.

jz et je sont littéralement la même instruction , c'est à dire la même opcode dans le code machine. ils font la même chose, mais ont un sens sémantique différent pour les humains . Les désassembleurs (et typiquement la sortie asm des compilateurs) n'en utiliseront qu'un seul, de sorte que la distinction sémantique est perdue.

cmp et sub jeu de ZF, lorsque leurs deux les entrées sont égales (c'est à dire la soustraction résultat est 0). je (saut si égal) est le synonyme sémantiquement pertinent.

test %eax,%eax / and %eax,%eax définit de nouveau ZF quand le résultat est zéro, mais il n'y a pas de test" d'égalité". ZF après test ne vous dit pas si les deux opérandes étaient égales. Ainsi jz (saut si Zéro) est le synonyme sémantiquement pertinent.

18
répondu Peter Cordes 2017-12-16 13:23:35

cet extrait de code provient d'un sous-programme auquel on a donné un pointeur vers quelque chose, probablement une structure ou un objet. La 2ème ligne déréfère ce pointeur, récupérant une valeur de cette chose-peut-être elle-même un pointeur ou peut-être juste un int, stocké comme son 2ème membre (offset +4). Les lignes 3 et 4 testent cette valeur pour zéro (nul si c'est un pointeur) et sautent les quelques opérations suivantes (non indiquées) si elle est zéro.

le test pour Zéro est parfois codé comme un comparer à une valeur zéro littérale immédiate, mais le compilateur (ou humain? celui qui a écrit ceci aurait pu penser qu'un test op fonctionnerait plus rapidement - en tenant compte de tous les trucs modernes de CPU comme pipelining et Registre renommer. C'est le même sac de trucs qui contient L'idée de vider un registre avec XOR EAX,EAX (que j'ai vu sur la plaque d'immatriculation de quelqu'un dans le Colorado!) plutôt que l'évidente, mais peut-être plus lente MOVEAX, #0 (j'utilise une notation plus ancienne).

en asm, comme perl, TMTOWTDI.

5
répondu DarenW 2008-09-29 03:40:00

Si eax est zéro, il va effectuer un saut conditionnel, sinon il va continuer l'exécution à 319e9

3
répondu Mike Thompson 2008-09-29 01:25:07

dans certains programmes, ils peuvent être utilisés pour vérifier un dépassement de tampon. Tout en haut de l'espace alloué un 0 est placé. Après avoir entré les données dans la pile, il recherche le 0 au tout début de l'espace alloué pour s'assurer que l'espace alloué n'est pas débordé.

il a été utilisé dans l'exercice stack0 d'exploits-exercices pour vérifier s'il était débordé et s'il n'y avait pas et il y avait un zéro là, il afficherait "essayer à nouveau"

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret
0
répondu user7259278 2016-12-06 21:19:36

nous pourrions voir le jg e-mail jle Si testl %edx,%edx. jle .L3 nous pourrions facilement trouver jle est suit (SF^OF)|ZF , si %edx est zéro, ZF=1,mais si %edx n'est pas zéro et est -1, après le test L, Le OF=0,et le SF =1,donc le drapeau =true, qui mettent en œuvre saut .désolé, mon anglais est mauvais

-2
répondu cbei_you 2017-03-14 07:35:26