Search code examples
c++cgccx86reverse-engineering

Int vs Double in assembly


Why GCC compiler adds this three lines when using double and don't when there is Int?


With int:

#include <cstdio>

int main(){
    int i = 1;
}

==>

main:
        push    ebp
        mov     ebp, esp
        sub     esp, 16
        mov     DWORD PTR [ebp-4], 1
        mov     eax, 0
        leave
        ret

With double:

#include <cstdio>

int main(){
    double i = 1;
}

==>

main:
        lea     ecx, [esp+4]            // This three lines
        and     esp, -8                 //  ...
        push    DWORD PTR [ecx-4]       //  ...
        push    ebp
        mov     ebp, esp
        push    ecx
        sub     esp, 20
        fld1
        fstp    QWORD PTR [ebp-16]
        mov     eax, 0
        add     esp, 20
        pop     ecx
        pop     ebp
        lea     esp, [ecx-4]
        ret

Similar happens when using pointers, for example, int *s = new int(4);

Can you explain why this happens, and why not always?


Solution

  • In the case of a double in automatic scope (on the stack), the extra code aligns the stack frame at an even 8 byte boundary, so that the double variable is stored at a memory address with suitable alignment. The stack pointer, when entering the function, is not guaranteed to be aligned on an even 8-byte boundary, and the compiler adds the extra code to make it so.

    That's what the and esp, -8 does. -8 is 0xFFFFFFF8. This clears the last 3 bits of esp, using and, making it point to an even 8 byte boundary memory address, adjusting it down (the stack grows from high to low memory addresses).