`testl` eax contre eax?

J’essaie de comprendre une certaine assemblée.

L’assemblage comme suit, je m’intéresse à la ligne de 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 sharepoint 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?

Il eax si eax est eax 0 ou supérieur ou inférieur. Dans ce cas, le saut est pris si eax est 0.

La signification de test est à AND les arguments et vérifie le résultat pour zéro. Donc, ce code teste si EAX est nul ou non. je vais sauter si zéro.

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

L’instruction de test effectue une opération AND logique entre les opérandes mais n’écrit 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, l’indicateur de signe si le bit le plus élevé est défini et d’autres indicateurs également.

L’instruction Jump if Equal (je) saute si le drapeau zéro est défini.

Vous pouvez traduire le code en un code plus lisible comme celui-ci:

 cmp eax, 0 je somewhere 

Cela a la même fonctionnalité mais nécessite des octets plus d’espace de code. C’est la raison pour laquelle le compilateur a émis un test au lieu d’une comparaison.

test est comme and , sauf qu’il écrit seulement FLAGS, laissant ses deux entrées non modifiées. Avec deux entrées différentes , il est utile de tester si certains bits sont tous nuls 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 ses deux bits 2 à zéro).


test eax,eax définit tous les drapeaux exactement de la même manière que cmp eax, 0 :

  • CF et OF effacés (AND / TEST fait toujours cela et soustraire zéro ne produit jamais un report)
  • ZF, SF et PF en fonction de la valeur dans EAX. ( a = a&a = a-0 )

(Sauf pour les AF obsolètes (indicateur de portage auxiliaire, utilisé par les instructions ASCII / BCD). TEST le laisse indéfini , mais CMP le définit “en fonction du résultat” . Comme la soustraction de zéro ne peut pas produire de report du 4 au 5 bit, CMP devrait toujours effacer AF).


TEST est plus petit (pas immédiat) et parfois plus rapide (peut se fusionner en une seule opération de comparaison et de twig sur un plus grand nombre de processeurs que CMP). Cela permet de test l’idiome préféré pour tester un registre à zéro ou non .

La seule raison commune pour utiliser CMP avec un 0 immédiat est lorsque vous voulez comparer avec un opérande de mémoire (par exemple, cmpb $0, (%esi) pour vérifier un octet de terminaison à la fin d’un style C de longueur implicite). chaîne).


AVX512F ajoute kortestw k1, k2 et AVX512DQ / BW (Skylake mais pas KNL), ajoutent ktestb/w/d/q k1, k2 , qui fonctionnent sur les registres de masque AVX512 (k0..k7) de la même manière que les instructions OR ou AND entières.

kortestw k1,k1 est le moyen idiomatique de créer une twig / cmovcc / setcc basée sur un résultat de comparaison AVX512, remplaçant SSE / 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 le même opcode dans le code machine. Ils font la même chose mais ont une signification sémantique différente pour les humains . Les désassembleurs (et généralement les fichiers asm générés par les compilateurs) n’en utiliseront qu’un, de sorte que la distinction sémantique est perdue.

cmp et sub ensemble ZF lorsque leurs deux entrées sont égales (le résultat de la soustraction est 0). je (sauter si égal) est le synonyme sémantiquement pertinent.

test %eax,%eax / and %eax,%eax définit à nouveau ZF lorsque 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 égaux. Donc jz (sauter si zéro) est le synonyme sémantiquement pertinent.

Cet extrait de code provient d’une sous-routine à laquelle on a donné un pointeur sur quelque chose, probablement une structure ou un object. La deuxième ligne déréférencera ce pointeur, récupérant une valeur de cette chose – peut-être elle-même un pointeur ou peut-être juste un int, stocké en tant que second membre (offset +4). Les 3ème et 4ème lignes testent cette valeur pour zéro (NULL si c’est un pointeur) et ignorent les quelques opérations suivantes (non affichées) si elles sont nulles.

Le test de zéro est parfois codé comme une comparaison avec une valeur zéro littérale immédiate, mais le compilateur (ou l’homme?) Qui a écrit ceci pourrait penser qu’un testl fonctionnerait plus rapidement – en prenant en compte renommer. C’est à partir du même sac de trucs que l’idée de supprimer un registre avec XOR EAX, EAX (que j’ai vu sur la plaque d’immasortingculation de quelqu’un au Colorado!) Plutôt que l’évident mais peut-être plus lent MOV EAX, # 0 ).

Dans asm, comme perl, TMTOWTDI.

Si eax est nul, il effectuera le saut conditionnel, sinon il continuera l’exécution à 319e9

Dans certains programmes, ils peuvent être utilisés pour rechercher un dépassement de tampon. Au sumt de l’espace alloué, un 0 est placé. Après avoir entré des données dans la stack, il recherche le 0 au tout début de l’espace alloué pour s’assurer que l’espace alloué n’est pas saturé.

Il a été utilisé dans l’exercice d’exploits-exercices pour vérifier s’il était débordé et s’il n’y avait pas de zéro, il afficherait «Réessayer».

 0x080483f4 : push ebp 0x080483f5 : mov ebp,esp 0x080483f7 : and esp,0xfffffff0 0x080483fa : sub esp,0x60 0x080483fd : mov DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack 0x08048405 : lea eax,[esp+0x1c] 0x08048409 : mov DWORD PTR [esp],eax 0x0804840c : call 0x804830c  0x08048411 : mov eax,DWORD PTR [esp+0x5c] 0x08048415 : test eax,eax ; checks if its zero 0x08048417 : je 0x8048427  0x08048419 : mov DWORD PTR [esp],0x8048500 0x08048420 : call 0x804832c  0x08048425 : jmp 0x8048433  0x08048427 : mov DWORD PTR [esp],0x8048529 0x0804842e : call 0x804832c  0x08048433 : leave 0x08048434 : ret 

nous pourrions voir le jg le jle Si testl %edx,%edx. jle .L3 testl %edx,%edx. jle .L3 on pourrait facilement trouver jle est convenable (SF^OF)|ZF , si% edx vaut zéro, ZF = 1, mais si% edx n’est pas nul et vaut -1, après le testl, le OF = 0, et le SF = 1, donc le drapeau = true, qui implémente le saut .sorry, mon anglais est pauvre