Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redundant instruction in compiled code [duplicate]

Possible Duplicate:
What's the point of LEA EAX, [EAX]?

During a disassembly practice, I have observed the following code:

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;
}

compiling using vc++ 2008 with optimization:

cl /Ox test.cpp

disassembly of main function:

.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

Now, I am not exactly an expert, as you can see from the example code, but I was able to figure out this assembly listing, taking into account that I wrote the original code. The only thing that bothers me is the following line:

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

Why does the compiler do that? It doesn't effect any register or flag, and it seems like a redundant code. The only thing I can think about is that the compiler aligns the code where the jmp goes to in the second loop (loc_401020) is this might be the reason?

like image 570
MByD Avatar asked Nov 02 '11 21:11

MByD


3 Answers

Yes, it looks like it's inserting padding to align the jump target. If you use /Fa to have the compiler produce assembly output, that'll show up as npad 7, making it explicit that it's inserting padding. From there, it's up to the assembler to pick out the most efficient sequence of instructions it can find to use up the specified space while using as little CPU time as possible.

like image 151
Jerry Coffin Avatar answered Nov 18 '22 12:11

Jerry Coffin


The useless instruction is just before a label and the label is aligned. It looks like a kind of nop to me (assemblers can generate one-instruction nop of various lengths because it's more efficient than several of the "standard" one-byte nop when execution has to go through them).

like image 33
Pascal Cuoq Avatar answered Nov 18 '22 11:11

Pascal Cuoq


Your guess is correct. That instruction is effectively a 7-byte NOP to align the label at the start of the loop to a 16-byte boundary. If you were to look at the actual encoding of that instruction, you'd probably notice that not only does it not have any effect on any register or flag, it also uses a 4-byte encoding for the immediate offset of 0 when it could just as easily use a shorter encoding. All of this is to consume the right number of code bytes while making the instruction as efficient to execute as possible.

like image 2
Orion Avatar answered Nov 18 '22 11:11

Orion