首先看看上面這段c**,按照c語言的運算子優先順序規則,這個程式的執行結果應該是18(首先執行完小括號裡的三個++a,這時a就為6,然後在執行加法運算,3個a相加自然等於18)。
可是我在vc6.0下編譯這段程式時,如果編譯為debug版,則輸出結果為16,如果編譯為release版本,則輸出結果為18。
為什麼debug版本的結果會是16呢???怎麼想也不應該是16啊。於是自然就想到了看看這段程式對應debug版的彙編**吧,看看vc的編譯器究竟把這段**編譯成什麼樣子了。為了簡單起見,我只分析子函式bug()。
int a=3,b;
b=(++a)+(++a)+(++a);
以上這兩行**在vc的debug版本下對應的彙編**為:
0040102f 8b 45 fc mov eax,dword ptr [ebp-4]
00401032 83 c0 01 add eax,1
00401035 89 45 fc mov dword ptr [ebp-4],eax
00401038 8b 4d fc mov ecx,dword ptr [ebp-4]
0040103b 83 c1 01 add ecx,1
0040103e 89 4d fc mov dword ptr [ebp-4],ecx
00401041 8b 55 fc mov edx,dword ptr [ebp-4]
00401044 03 55 fc add edx,dword ptr [ebp-4]
00401047 8b 45 fc mov eax,dword ptr [ebp-4]
0040104a 83 c0 01 add eax,1
0040104d 89 45 fc mov dword ptr [ebp-4],eax
00401050 03 55 fc add edx,dword ptr [ebp-4]
00401053 89 55 f8 mov dword ptr [ebp-8],edx
上面這段彙編**的意思,相信只要懂得彙編的朋友都可以很容易看懂,不過為了照顧一下大眾,我還是簡單說明一下吧,根據變數定義的位置可以知道,ebp-4就是變數a的位址,ebp-8就是變數b的位址,於是以上**可以簡化為:
mov eax,a
add eax,1
mov a,eax
//此時a=4
mov ecx,a
add ecx,1
mov a,ecx
//此時a=5
mov edx,a
add edx,a
//此時edx=10
mov eax,a
add eax,1
mov a,eax
//此時a=6
add edx,a
mov b,edx
//此時b=16
所以,debug版本的最後輸出結果自然就是16,但我認為這是乙個錯誤的結果。但是為什麼release版的又能返回我認為正確的結果18呢?於是,隨後我又用od對release版的程式進行了逆向分析,大家看圖:
這個結果讓我感到很意外,在release版中,子函式bug()居然被優化成了直接返回結果:0x12(十進位制就是18)。
至於其中為什麼會優化成那樣的原因我可就不知道了,這要去問問微軟那些開發這個vc編譯器(這裡順便提一下:vc6.0自帶的 c/c++編譯器的版本為:version 12.00.8804)的工程師了,呵呵。當然也可以通過逆向分析這個vc編譯器,從而找到答案,不過本人能力有限,目前還很難辦到,若哪位大牛路過,還請不吝賜教。
VC6 0編譯器的一些options
進行編譯,就能生成乙個簡單的hello.exe檔案。其實這個可執行檔案的產生需要呼叫兩個程式 cl.exe和link.exe。先看一看cl.exe的options nologo mld w3 gm gx zi od d win32 d debug d windows d mbcs fp debug ...
VC6 0 編譯器BUG修正收集
1.error spawning bscmake.exe 解決 project,setting,browse info,去掉選項build browse info file 2.fatal error lnk1210 exceeded internal ilk size limit relink w...
關於VC6 0 和其他VS編譯器
最近想寫一些 mfc應用程式,在發布的時候遇到了幾個問題,從中得到了一點體會,與大家分享一下。遇到的幾方面問題的起因 1.自己用vs 剛換win7 編譯好的程式在其他人那裡無法執行,提示缺少 mfc庫 2.上面的問題好解決,用靜態 mfc方式重新發布,卻發現原本 200多 k的程式變成了 1m多。3...