我有一个非常简单的程序,我的目标是研究编译器如何将值推入不同的寄存器。但是现在,该行为比预期的要复杂得多,至少在 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/