底層的重要性

有時候,我更想念以前編寫BASIC和彙編的時代。

我相信有很多人用C語言寫了如下程序:

int main()
{
    return 0;
}

然後編譯成xxx.exe文件,然後用反編譯軟件(OD)打開查看:(結果因編譯器不同而不同)

... ...
00401A10   .  56            push esi
00401A11   .  53            push ebx                                 ;  zero.00401A10
00401A12   .  83EC 14       sub esp,0x14
00401A15   .  833D 64704000>cmp dword ptr ds:[0x407064],0x2
00401A1C   .  8B4424 24     mov eax,dword ptr ss:[esp+0x24]          ;  zero.00401A10
00401A20   .  74 0A         je short zero.00401A2C
00401A22   .  C705 64704000>mov dword ptr ds:[0x407064],0x2
00401A2C   >  83F8 02       cmp eax,0x2
00401A2F   .  74 12         je short zero.00401A43
00401A31   .  83F8 01       cmp eax,0x1
00401A34   .  74 3F         je short zero.00401A75
00401A36   >  83C4 14       add esp,0x14
00401A39   .  B8 01000000   mov eax,0x1
00401A3E   .  5B            pop ebx                                  ;  ntdll_12.779F9264
00401A3F   .  5E            pop esi                                  ;  ntdll_12.779F9264
00401A40   .  C2 0C00       retn 0xC
00401A43   >  BE 14904000   mov esi,zero.00409014
00401A48   .  81EE 14904000 sub esi,zero.00409014
00401A4E   .  83FE 03       cmp esi,0x3
00401A51   .^ 7E E3         jle short zero.00401A36
00401A53   .  31DB          xor ebx,ebx                              ;  zero.00401A10
00401A55   >  8B83 14904000 mov eax,dword ptr ds:[ebx+0x409014]
00401A5B   .  85C0          test eax,eax
00401A5D   .  74 02         je short zero.00401A61
00401A5F   .  FFD0          call eax
00401A61   >  83C3 04       add ebx,0x4
00401A64   .  39DE          cmp esi,ebx                              ;  zero.00401A10
00401A66   .^ 75 ED         jnz short zero.00401A55
00401A68   .  83C4 14       add esp,0x14
00401A6B   .  B8 01000000   mov eax,0x1
00401A70   .  5B            pop ebx                                  ;  ntdll_12.779F9264
00401A71   .  5E            pop esi                                  ;  ntdll_12.779F9264
00401A72   .  C2 0C00       retn 0xC
00401A75   >  8B4424 28     mov eax,dword ptr ss:[esp+0x28]          ;  zero.00400000
... ...

這是什麼鬼東西

好吧,所以說無論你編寫怎樣的代碼,最後也將變成無數行彙編,那爲何不直接寫彙編呢?那是因爲。。。我們懶嘛!

高級語言的好處在這裏就可以體現出來:可讀性!  但是隨之而來的還有大量冗餘的指令 <stdio.h> 中的printf()函數就有上千條指令,雖然說這多餘的部分可以使該軟件運行在其他的操作系統平臺上,增加兼容性,但是這對我們真正瞭解電腦的工作原理沒有好處。在軟件運行中的很多問題bug是隻有去查看反彙編才能體會的。

比如說:

#include<stdio.h>
int main()
{
    int a=0,b;
    b=(++a)+(++a)+(++a);
    printf("%d\n",b);
    return 0;
}

這段代碼的運行結果是什麼?  

結果是不確定的,取決於你使用哪種編譯器。如果你用gcc來編譯的話,應該是輸出:7  用VC編譯輸出: 9

(發生了什麼?)

我們一般認爲程序是這樣運行的:a++;b+=a;a++;b+=a;a++;b+=a;所以應該輸出b=1+2+3=6纔對

(大家可以用反彙編查看,但考慮到不一定大家都看得懂,所以就不直接放出來了)

然而事實上依據從左向右的順序, 相當於b=((++a)+(++a))+(++a)

b=(a+(++a))+(++a)           //第一次脫括號的結果, 這時a=1
b=(a+a)+(++a)               //第二次脫括號的結果. 這時a=2
b=(2+2)+(++a)  
b=4+(++a)                   //第三次脫括號的結果, 這時a=2
b=4+a                       //第四次脫括號的結果, 這時a=3
b=4+3=7
//題外話:++a 在c++中是左值表達式, 但在c中不是左值表達式

在VC中是這樣的:

a++;a++;a++;
b=a+a+a=9

可以看出其中的區別

所以在學習高級語言的時候,有必要了解一下軟件底層的實現,而不是成爲“碼農”。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章