我有一个非常简单的程序,我的目标是研究编译器如何将值推入不同的寄存器。但是现在,该行为比预期的要复杂得多,至少在 Debug模式下是如此。

这里发生了什么?

#include <cstdio>

struct A
{
    int B;
    A() : B(0) { }
};

int main()
{
    A a;
    A b(a);
    printf("%d", b.B);
    printf("%d", a.B);
    return 0;
}

这是Visual Studio中反汇编的样子:
int main()
{
01048210  push        ebp
01048211  mov         ebp,esp
01048213  sub         esp,0D8h
01048219  push        ebx
0104821A  push        esi
0104821B  push        edi
0104821C  lea         edi,[ebp-0D8h]
01048222  mov         ecx,36h
01048227  mov         eax,0CCCCCCCCh
0104822C  rep stos    dword ptr es:[edi]
    A a;
0104822E  lea         ecx,[a]
01048231  call        A::A (104678Ah)
    A b(a);
01048236  mov         eax,dword ptr [a]
01048239  mov         dword ptr [b],eax
    printf("%d", b.B);
0104823C  mov         eax,dword ptr [b]
0104823F  push        eax
01048240  push        offset string "%d" (1093C6Ch)
01048245  call        @ILT+3885(_printf) (1046F32h)
0104824A  add         esp,8
    printf("%d", a.B);
0104824D  mov         eax,dword ptr [a]
01048250  push        eax
01048251  push        offset string "%d" (1093C6Ch)
01048256  call        @ILT+3885(_printf) (1046F32h)
0104825B  add         esp,8
}

第一行在此answer中进行了说明,它们在那里保留帧指针,以便可以生成漂亮的堆栈跟踪。

但是接下来的几行令人困惑:为什么要从esp中减去216(0D8h)?

这些在main之后但在代码A a;第一行之前的行是什么?

编辑:将运行时检查设置为默认值后,反汇编要小得多:
int main()
{
00247110  push        ebp
00247111  mov         ebp,esp
00247113  sub         esp,48h
00247116  push        ebx
00247117  push        esi
00247118  push        edi
    A a;

编辑2:在 Release模式(/ Ox)中,a和b已完全优化,并且堆栈上根本没有分配内存:
int main()
{
    A a;
    A b(a);
    printf("%d", b.B);
00B41000  push        0
00B41002  push        0B499A0h
00B41007  call        printf (0B4102Dh)
    printf("%d", a.B);
00B4100C  push        0
00B4100E  push        0B499A4h
00B41013  call        printf (0B4102Dh)
00B41018  add         esp,10h
    return 0;
0127101B  xor         eax,eax
}
0127101D  ret

编辑3:这是使用gcc -m32 -O3 -mpreferred-stack-boundary=2的结果(感谢@CodyGray)。
.LC0:
        .string "%d"
Test():
        push    0
        push    OFFSET FLAT:.LC0
        call    printf
        pop     eax
        pop     edx
        push    0
        push    OFFSET FLAT:.LC0
        call    printf
        pop     ecx
        pop     eax
        ret

最佳答案

00CC8223  sub         esp,0D8h

为局部变量分配堆栈空间。



你指的是什么?

关于c++ - 拆卸后的说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43499212/

10-12 04:17