9 Stimmen

Redundante Anweisungen in kompiliertem Code

Mögliches Duplikat:
Was ist der Sinn von LEA EAX, [EAX]?

Bei einer Demontageübung habe ich den folgenden Code beobachtet:

test.cpp:

#include <stdio.h>

int main(int argc, char * argv[]) {
    for (int i = 0; i < 10 ; ++i) {
        printf("%i\n", i);
    }
    int i = 0;
    while ( i < 10) {
        printf("%i\n", i);
        ++i;
    }
    return 0;
}

Kompilieren mit vc++ 2008 mit Optimierung:

cl /Ox test.cpp

Demontage der Hauptfunktion:

.text:00401000 var_4           = dword ptr -4 ; BTW, IDA fails to see that esi is pushed to save it, not to allocate space to local variable
.text:00401000
.text:00401000                 push    esi
.text:00401001                 xor     esi, esi
.text:00401003
.text:00401003 loc_401003:                             ; CODE XREF: sub_401000+15j
.text:00401003                 push    esi
.text:00401004                 push    offset byte_40A150
.text:00401009                 call    sub_401038      ; printf 
.text:0040100E                 inc     esi
.text:0040100F                 add     esp, 8
.text:00401012                 cmp     esi, 0Ah
.text:00401015                 jl      short loc_401003
.text:00401017                 xor     esi, esi
.text:00401019                 lea     esp, [esp+0]
.text:00401020
.text:00401020 loc_401020:                             ; CODE XREF: sub_401000+32j
.text:00401020                 push    esi
.text:00401021                 push    offset unk_40A154
.text:00401026                 call    sub_401038      ; printf 
.text:0040102B                 inc     esi
.text:0040102C                 add     esp, 8
.text:0040102F                 cmp     esi, 0Ah
.text:00401032                 jl      short loc_401020
.text:00401034                 xor     eax, eax
.text:00401036                 pop     esi
.text:00401037                 retn

Nun bin ich nicht gerade ein Experte, wie Sie aus dem Beispielcode ersehen können, aber ich war in der Lage, dieses Assembler-Listing herauszufinden, da ich den Originalcode geschrieben habe. Das einzige, was mich stört, ist die folgende Zeile:

.text:00401019                 lea     esp, [esp+0]

Warum macht der Compiler das? Es wirkt sich auf kein Register oder Flag aus, und es scheint ein überflüssiger Code zu sein. Das Einzige, woran ich denken kann, ist, dass der Compiler den Code an der Stelle ausrichtet, an die der jmp in der zweiten Schleife geht (loc_401020), könnte das der Grund sein?

6voto

Jerry Coffin Punkte 452852

Ja, es sieht so aus, als ob das Sprungziel durch Einfügen von Füllmaterial ausgerichtet werden soll. Wenn Sie /Fa damit der Compiler eine Assembler-Ausgabe erzeugt, wird diese angezeigt als npad 7 und macht damit deutlich, dass es eine Füllung einfügt. Von da an ist es Sache des Assemblers, die effizienteste Befehlsfolge zu finden, die den angegebenen Platz ausnutzt und dabei so wenig CPU-Zeit wie möglich verbraucht.

2voto

Pascal Cuoq Punkte 77147

Die unbrauchbare Anweisung steht unmittelbar vor einem Etikett, und das Etikett wird ausgerichtet. Es sieht aus wie eine Art von nop (Assembler können Ein-Befehl-Anweisungen erzeugen nop verschiedener Längen, weil es effizienter ist als mehrere der "Standard"-Ein-Byte nop wenn die Ausführung über sie laufen muss).

2voto

Orion Punkte 381

Ihre Vermutung ist richtig. Diese Anweisung ist effektiv ein 7-Byte-NOP, um das Label am Anfang der Schleife an einer 16-Byte-Grenze auszurichten. Wenn Sie sich die tatsächliche Kodierung dieses Befehls ansehen würden, würden Sie wahrscheinlich feststellen, dass er nicht nur keine Auswirkungen auf irgendein Register oder Flag hat, sondern auch eine 4-Byte-Kodierung für den unmittelbaren Offset von 0 verwendet, obwohl er genauso gut eine kürzere Kodierung verwenden könnte. All dies dient dazu, die richtige Anzahl von Code-Bytes zu verbrauchen und gleichzeitig die Ausführung des Befehls so effizient wie möglich zu gestalten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X