2010-07-29 37 views
14

我剛剛注意到一些奇怪的空主函數的彙編語言代碼。用Visual C++編譯器解釋空C`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 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 
  1. 爲什麼地球上它保留了功能192個字節,其中沒有任何變量
  2. 怎麼了四大行:1號線, 2,第3行,第4行?它試圖做什麼&爲什麼?
+0

爲什麼不突出顯示代碼語法? – claws 2010-07-29 13:25:05

+0

裝配非空主語句時產生了什麼程序集,以及將main的返回類型更改爲int時會發生什麼? – 2010-07-29 13:29:17

+5

值得指出的是主要回報int。使用void作爲main不是很好。 – nmichaels 2010-07-29 13:30:21

回答

15

您指出的四條代碼行是調試版本,用「清除」特殊值(0xCCCCCCCC)清除局部變量空間。

我不知道爲什麼有192個字節的看起來死的空間,但可能是VC++建立一些警衛空間到您的本地變量區域,以嘗試檢測堆棧粉碎。

如果從Debug切換到Release版本,您可能會得到非常不同的輸出。

+1

爲什麼'0xCCCCCCCC' ='1100 1100 1100 1100 1100 1100 1100 1100'?不會用0x00000000清除會更有意義? – claws 2010-07-29 13:39:09

+0

@claws:微軟選擇了這個值,因爲它很明顯,很容易識別你的程序是否最終使用了一個未初始化的變量。使用零會掩蓋很多潛在的錯誤,因爲經常將變量初始化爲零,並且讓編譯器在調試版本中這樣做會導致發佈版本失敗。 – 2010-07-29 13:42:18

+0

@Greg Hewgill:如何在Visual Studio中查看Release配置中的反彙編?我在關閉支架上放置了一個斷點並查看反彙編。這似乎不能在發佈模式下工作。 – claws 2010-07-29 14:06:12

18

Greg已經解釋了編譯器如何生成代碼來診斷由/ RTCu編譯選項啓用的未初始化的局部變量。 0xcccccccc值被選擇爲獨特的,並且在調試器中容易識別。並確保在未初始化的指針被解除引用時程序炸彈。並確保程序在作爲代碼執行時終止程序。 0xcc非常適合完成所有這些工作,它是INT3的指令操作碼。

在堆棧框架中分配的神祕的192個字節是支持編輯+繼續功能,/ ZI編譯選項。它允許您在斷點處於活動狀態時編輯代碼。並且將一些局部變量添加到一個函數中,這192個字節可用於爲那些添加的本地人提供空間。超過這個空間將會讓IDE強迫你重建你的程序。

btw:如果您在代碼中使用遞歸,會導致問題。調試版本將以更快的速度與這個網站的名字相撞。通常不是很多問題,您可以使用實際的數據集大小進行調試。

+2

向上,提供的信息是晦澀但令人着迷。 – mickeyf 2010-07-29 14:50:06

+0

你說的是正確的http://stackoverflow.com/questions/370195/when-and-why-will-an-os-initialise-memory-to-0xcd-0xdd-etc-on-malloc-free-new – 2014-06-19 08:36:43