我有一个非常简单的程序,我的目标是研究编译器如何将值推送到不同的寄存器.但现在这种行为比预期的要复杂得多,至少在调试模式下如此.
这里发生了什么?
#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  
}
在这个答案中解释了第一行,它们用于键入帧指针,以便可以生成好的堆栈跟踪.
但下一行令人困惑:为什么从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:在发布模式(/ 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  
为局部变量分配堆栈空间.
主要之后,但在第一条指令做之前,这些线是什么?
你指的是什么?