Dupliqué possible: strong>
Pourquoi ce code complexe est-il émis pour diviser un entier signé par une puissance de deux? p>fond h2>
Je vais simplement apprendre x86 ASM en examinant le code binaire généré par le compilateur. p>
code compilé à l'aide du compilateur C ++ dans Visual Studio 2010 Beta 2 . P>
0040100A |. 8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX] 00401010 |> 99 /CDQ 00401011 |. 2BC2 |SUB EAX,EDX
4 Réponses :
Le Le LEA EBX, [EBX] CODE> est juste une opération NOP. Son but est d'aligner le début de la boucle en mémoire, ce qui le rendra plus rapide. Comme vous pouvez le constater ici, le début de la boucle commence à l'adresse 0x00401010, qui est divisible par 16, grâce à cette instruction. P>
CDQ code> et
Sub EAX, EDX CODE> Opérations Assurez-vous que la Division arrondira un nombre négatif sur zéro - sinon, SAR SAR serait arrondir, donnant des résultats incorrects pour négatif chiffres. p>
Mauvais: EBX est utilisé par __tmaincrtstartu pour vérifier s'il s'agit d'une application gérée, ce n'est donc pas un NOP et n'a rien d'emballage avec l'alignement
Vous vous trompe vous-même. Lea EBX, [EBX] CODE> est équivalent à
MOV EBX, EBX CODE> - Il ne fait rien. La valeur du registre EBX n'est pas vérifiée pour quoi que ce soit.
Il ne semble rien faire car Ebx est initié avec zéro (XOR EBX, EBX) dans __tmaincrTstartup avant que le principal est appelé. Démontez simplement le code dans __tmaincrtstartup et vous verrez. Dès que les retours principaux, EBX est vérifié. Si vous par exemple. Attribuez explicitement à EBX avant de revenir en main, le compilateur conservera la valeur de EBX (zéro pour l'application native) et la restaurera lorsque le rendement principal.
Jn: Le fait que EBX détient une valeur est hors de propos, car cette instruction ne le comparait pas avec quoi que ce soit ou modifier. Cela aurait pu accéder à tout autre registre. Si vous regardez le code créé par Visual Studio, vous verrez ce type de code avant la plupart des boucles intérieures - et le début de la boucle sera aligné sur 16 (ou peut-être 8) octets.
Interjay: Vous avez raison lorsque vous dites que cette opération est utilisée pour aligner la boucle. L'insertion des NOPS au début rend VS Insérer lea ECX, [ECX + 0]. D'autre part, EBX est en cause utilisé par le temps d'exécution pour vérifier s'il s'agit d'une application gérée. L'arrêt du temps d'exécution est traité différemment s'il est
Le tout
y = (y + (y < 0)) >> 1;
Pas -2/2 + 1 code>, mais plutôt
(- 2 + 1) >> 1 code>. Ceci évalue à
-1 code>.
Cela ne répond pas vraiment à la question, mais est un indice utile. Au lieu de vous brouiller avec la chose ollydbg.exe, vous pouvez créer un studio visuel générer le fichier ASM pour vous, qui a le bonus ajouté qu'il peut placer dans le code source d'origine comme des commentaires. Ce n'est pas une grosse affaire pour votre petit projet actuel, mais comme votre projet se développe, vous risquez de passer à une juste durée de déterminer quel code d'assemblage correspond à quel code source.
de la ligne de commande, vous voulez le Options FAS et / FA ( MSDN ) . P>
Voici une partie de la sortie pour votre code d'exemple (j'ai compilé le code de débogage, de sorte que l'.asm est plus long, mais vous pouvez faire la même chose pour votre code optimisé): P>
_wmain PROC ; COMDAT ; 8 : { push ebp mov ebp, esp sub esp, 216 ; 000000d8H push ebx push esi push edi lea edi, DWORD PTR [ebp-216] mov ecx, 54 ; 00000036H mov eax, -858993460 ; ccccccccH rep stosd ; 9 : int x=5; int y=1024; mov DWORD PTR _x$[ebp], 5 mov DWORD PTR _y$[ebp], 1024 ; 00000400H $LN2@wmain: ; 10 : while(x) { x--; y/=2; } cmp DWORD PTR _x$[ebp], 0 je SHORT $LN1@wmain mov eax, DWORD PTR _x$[ebp] sub eax, 1 mov DWORD PTR _x$[ebp], eax mov eax, DWORD PTR _y$[ebp] cdq sub eax, edx sar eax, 1 mov DWORD PTR _y$[ebp], eax jmp SHORT $LN2@wmain $LN1@wmain: ; 11 : return x+y; mov eax, DWORD PTR _x$[ebp] add eax, DWORD PTR _y$[ebp] ; 12 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 _wmain ENDP
Merci, c'est très utile. J'utilise OllyDBG car c'est un outil aussi soigné, il met en évidence les valeurs de registre modifiées par la dernière instruction, attire les instructions JMP ira, pour moi, il est beaucoup plus pratique de suivre les instructions de Olly que dans toute autre chose.
Oh oui, pas de question Un débogueur complet de montage comme OLLYDBG est un excellent outil. Je suggérais simplement un autre outil pour votre boîte à outils.
La raison pour laquelle le compilateur émet ceci: au lieu de l'équivalent sémantique: p> .. est-ce que c'est plus rapide pour le processeur pour exécuter une instruction de 6 octets à six instructions de 1 octet. C'est tout. P> p>