J'essaie de comprendre une assemblée.
En ce qui concerne l’Assemblée, la ligne testl
m’intéresse:
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 le point testl
entre %eax
et %eax
? Je pense que les détails de ce que ce code n'a pas d'importance, j'essaie seulement de comprendre le test avec lui-même - la valeur ne serait-elle pas toujours vraie?
Il vérifie si eax
est égal à 0 ou supérieur ou inférieur. Dans ce cas, le saut est pris si eax
est 0.
La signification de test
est d'ET AND les arguments ensemble et vérifiez le résultat pour zéro. Donc, ce code teste si EAX est égal à zéro ou non. je
sautera si zéro.
En passant, cela génère une instruction plus petite que cmp eax, 0
, raison pour laquelle les compilateurs le font généralement de cette façon.
L'instruction de test effectue une opération logique AND entre les opérandes mais ne réécrit pas le résultat dans un registre. Seuls les drapeaux sont mis à jour.
Dans votre exemple, test eax, eax définira l'indicateur zéro si eax est égal à zéro, l'indicateur de signe si le bit le plus élevé est défini et certains autres indicateurs.
L'instruction Jump if Equal (je) saute si l'indicateur zéro est défini.
Vous pouvez traduire le code en un code plus lisible comme ceci:
cmp eax, 0
je somewhere
Cela a la même fonctionnalité mais nécessite quelques octets plus d'espace de code. C'est la raison pour laquelle le compilateur a émis un test au lieu d'une comparaison.
Cet extrait de code provient d'un sous-programme auquel un pointeur a été attribué, probablement une structure ou un objet. La 2ème ligne supprime ce pointeur en récupérant une valeur de cette chose - éventuellement un pointeur ou peut-être simplement un int, stocké comme son 2ème membre (offset +4). Les 3ème et 4ème lignes testent cette valeur à zéro (NULL s'il s'agit d'un pointeur) et ignorent les quelques opérations suivantes (non illustrées) si elle est égale à zéro.
Le test pour zéro est parfois codé comme une comparaison avec une valeur zéro littérale immédiate, mais le compilateur (ou l'homme?) Qui l'a écrit aurait pu penser qu'un test serait plus rapide - en prenant en compte tous les éléments modernes du processeur, tels que le traitement en pipeline et l'enregistrement. renommer. C’est dans le même jeu d’astuces que l’idée de nettoyer un registre avec XOR EAX, EAX (que j’ai vu sur la plaque d’immatriculation de quelqu'un dans le Colorado!) Plutôt qu’en raison du MOV EAX, n ° 0 utiliser une notation plus ancienne).
En asm, comme Perl, TMTOWTDI.
Si eax est égal à zéro, il effectuera le saut conditionnel, sinon il poursuivra son exécution à 319e9
Dans certains programmes, ils peuvent être utilisés pour vérifier un débordement de mémoire tampon. Tout en haut de l'espace alloué, un 0 est placé. Après avoir saisi des 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 saturé.
Il a été utilisé dans l'exercice d'empilage d'exploits-exercices pour vérifier s'il débordait et s'il n'y en avait pas et s'il y avait un zéro, l'affichage afficherait "Try again"
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