用visualc+解释空C`main`函数的奇怪组合+;编译程序
我刚刚注意到空main方法的一些奇怪的汇编语言代码用visualc+解释空C`main`函数的奇怪组合+;编译程序,c,visual-c++,assembly,C,Visual C++,Assembly,我刚刚注意到空main方法的一些奇怪的汇编语言代码 //filename: main.c void main() { } 拆卸: push ebp mov ebp,esp sub esp,0C0h; why on the earth is it reserving 192 bytes? push ebx push esi push edi ; good compiler. Its s
//filename: main.c
void main()
{
}
拆卸:
push ebp
mov ebp,esp
sub esp,0C0h; why on the earth is it reserving 192 bytes?
push ebx
push esi
push edi ; good compiler. Its saving ebx, esi & edi values.
lea edi,[ebp-0C0h] ; line 1
mov ecx,30h ; line 2
mov eax,0CCCCCCCCh ; line 3
rep stos dword ptr es:[edi] ; line 4
xor eax,eax ; returning value 0. Code following this line is explanatory.
pop edi ; restoring the original states of edi,esi & ebx
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
您指出的四行代码是调试构建,使用“clear”特殊值(
0xcccc
)清除局部变量空间
我不确定为什么会有192字节的死区,但这可能是VC++在局部变量区域中构建了一些保护空间来检测堆栈崩溃
如果从调试切换到发布版本,您可能会得到非常不同的输出。Greg已经解释了编译器如何生成代码来诊断未初始化的局部变量,该代码由/RTCu编译选项启用。0xCCCC值被选择为独特的,并且在调试器中易于识别。并确保程序在取消引用未初始化指针时爆炸。并确保在程序作为代码执行时终止程序。0xcc非常适合于做好所有这些工作,它是INT3的指令操作码 堆栈框架中分配的192字节用于支持编辑+继续功能/ZI编译选项。它允许您在断点处于活动状态时编辑代码。并向函数中添加局部变量,这192个字节可用于为添加的局部变量提供空间。超过该空间将使IDE强制您重建程序
顺便说一句:如果在代码中使用递归,这可能会导致问题。调试构建将以该站点的名称快速轰炸。通常不会有太大的问题,您可以使用实际的数据集大小进行调试。为什么不突出显示代码语法?当您组装非空的主语句时,会生成什么程序集,那么当你把main的返回类型改为int时会发生什么呢?值得指出的是main返回int。使用void作为main并不是好的jujuju。@Joe D:幸运的是,编译器通常不是大脑有行星大小的抑郁机器人。这通常是独立实现的定义。独立实现允许但不要求提供完整的c库。在独立实现中,STDC_HOSTED被定义为0,而在HOSTED中,它被定义为1。为什么
0xcccc
=1100
?用0x00000000清除不是更有意义吗?@claws:Microsoft选择该值是因为如果程序最终使用未初始化的变量,它是独特的,并且很容易识别。使用零会掩盖许多潜在的错误,因为变量通常会被初始化为零,而让编译器在调试版本中这样做会导致发布版本失败。@claws:对于返回0的空函数的发布模式版本,您的pastebin正是我所期望的。正如我所说,当编译器不发出任何不必要的代码时,您将得到非常不同的输出。@Greg Hewgill:啊,是的,我记得很清楚。事实上,一旦这个未初始化的模式给我们带来了一个巨大的问题,当一个客户报告一个只发生在发布版本中的bug时,我们就根本无法复制它。结果证明,我们使用的是未初始化的布尔值。在发布版本中,它通常为零,但在调试版本中,它从未为零。打开关于使用未初始化变量的警告是一个更好的主意。“特殊值”的术语是内存毒药。Up,用于提供晦涩但有趣的信息。你所说的是正确的