Int vs Double 汇编

Int vs Double in assembly

为什么 GCC 编译器在使用 double 时添加这三行,而在使用 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

加倍:

#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

使用指针时会发生类似情况,例如 int *s = new int(4);

你能解释为什么会发生这种情况吗?为什么不总是这样?

如果 double 在自动范围内(在堆栈上),额外的代码将堆栈帧对齐到偶数 8 字节边界,因此 double 变量存储在具有适当对齐方式的内存地址。进入函数时,堆栈指针不能保证在偶数 8 字节边界上对齐,编译器会添加额外的代码来实现。

这就是 and esp, -8 的作用。 -8 是 0xFFFFFFF8。这将使用 and 清除 esp 的最后 3 位,使其指向偶数 8 字节边界内存地址,将其向下调整(堆栈从高内存地址增长到低内存地址)。