從C語言到彙編,從彙編到C語言

2021-05-23 14:05:05 字數 4190 閱讀 2430

看雪一同志寫的文章,我覺得很基礎和有用,知識著眼於小處。積累才是王道!

一、迴圈語句與發彙編後的機器語言

1、for迴圈

下面是一段c語言的**,我們的目的是來看其反彙編的結果:

int myfunction(int a,int b) 

return c; 

} 前面的反彙編暫時不理它,這裡從for的地方開始反彙編,結果如下: 

for(i=0;i<50;i++) 

00412bc7  mov        dword ptr [i],0   // i=0; 給迴圈變數賦初值 

00412bce  jmp         myfunction+39h (412bd9h)// 跳到第一次迴圈處   

>  00412bd0  mov        eax,dword ptr [i]  

|   00412bd3  add         eax,1  // i++;修改迴圈變數

|   00412bd6  mov        dword ptr [i],eax  

|   00412bd9  cmp        dword ptr [i],32h //  比較 i 與50的關係, 檢查迴圈條件

|   00412bdd  jge          myfunction+4ah (412beah)  // 當 i>=50 [即 !(i<50) ] 時則跳出迴圈

|    

<  00412be8  jmp         myfunction+30h (412bd0h)  // 跳回去修改迴圈變數

00412bea  mov         eax,dword ptr [c]  

}可以看到for迴圈主要用這麼幾條指令來實現:mov進行初始化。jmp跳過迴圈變數改變**。cmp實現條件判斷,jge根據條件跳轉。

用jmp回到迴圈改變**進行下一次迴圈。所以for結構有以下的顯著特徵: 

mov 《迴圈變數》,《初始值》   ; 給迴圈變數賦初值 

jmp b       ;跳到第一次迴圈處 

a: (改動迴圈變數)       ;修改迴圈變數。 

… b: cmp 《迴圈變數》,《限制變數》  ;檢查迴圈條件 

jgp  跳出迴圈 

(迴圈體) 

…                

jmp a       ;跳回去修改迴圈變數 

2、do迴圈  

再看一下do迴圈,因為 do迴圈沒有修改迴圈變數的部分,所以比for迴圈要簡單一些。 

do  while(c< 100); 

00411a5e  cmp        dword ptr [c],64h   

00411a62  jl           myfunction+35h (411a55h)  

return c;

do迴圈就是乙個簡單的條件跳轉回去。只有兩條指令: 

cmp 《迴圈變數》,《限制變數》 

jl 《迴圈開始點》 

3、while迴圈

while(c<100) 

00411a64  jmp         myfunction+35h (411a55h)  

return c; 

很明顯,我們會發現while要更複雜一點。因為while除了開始的時候判斷迴圈條件之外,後面還必須有一條無條件跳轉回到迴圈開始的地方,共用三條指令實現: 

a: cmp 《迴圈變數》,《限制變數》 

jge  b 

( 迴圈體) 

… jmp a 

b: (迴圈結束了) 

這樣,我們對c語言中的迴圈結構的分析,就基本弄完了!當然,我們用同樣的方法也可以分析出c語言在「分支語句」、以及其它的資料結構中的c**與機器反彙編**的關係了!

二、分支語句

1、if-else 語句

為了觀察其彙編語句,下面是乙個簡單的if判斷結構:  

if(a>0 && a<10) 

else if( a>10 && a<100) 

else  

if 判斷都是使用cmp再加上條件跳轉指令。對於if( a && b)的情況,一般都是使用否決法。如果a不成立,立刻跳下乙個分支。依次,如果 b 不成立,同樣跳下一分支。 

cmp 條件 

jle 下乙個分支

所以開始部分的反彙編為: 

if(a>0 && a<10) 

00411a66  cmp       dword ptr [c],0  

00411a6a  jle         411a81h   ; 跳下乙個else if的判斷點 

00411a6c  cmp       dword ptr [c],0ah  

00411a70  jge        411a81h   ; 跳下乙個else if的判斷點 

else if 的和 else 的特點是,開始都有一條無條件跳轉到判斷結束處,阻止前面的分支執行結束後,直接進入這個分支。這個分支能執行到的唯一途徑只是,前面的判斷條件不滿足。

else 則在jmp之後直接執行操作。而else if則開始重複if之後的操作,用cmp比較,然後用條件跳轉指令時行跳轉。

else if( a>10 && a<100) 

00411a7f  jmp          411aa9h     ;直接跳到判斷塊外 

00411a81  cmp         dword ptr [c],0ah         ;比較+條件跳轉,目標為下乙個分支處 

00411a85  jle          411a9ch  

00411a87  cmp         dword ptr [c],64h  

00411a8b  jge          411a9ch  

else  

00411a9a  jmp        411aa9h   ;這裡是else,所以只有簡單的一條跳轉。 

return c;

2、switch-case 語句

switch 的特點是有多個判斷。因為 swtich 顯然不用判斷大於小於,所以都是je(因此,c語言中switch語句不支援float型別的變數),分別跳到每個case處。最後乙個是無條件跳轉,直接跳到default處。以下的**:  

switch(a) 

default: 

printf("a>10 && a<100"); 

} 反彙編的switch(a) 

00411a66  mov         eax,dword ptr [a]  

00411a69  mov         dword ptr [ebp-0e8h],eax  

00411a6f  cmp         dword ptr [ebp-0e8h],0  // case 0:

00411a76  je            411a83h  

00411a78  cmp         dword ptr [ebp-0e8h],1  // case 1:

00411a7f  je            411a90h  

00411a81  jmp         411a9fh  // default:

之外。從這裡我們可以發現:switch語句裡,完成「比較判斷」的指令會與「case」指令的兩部分,在彙編中,不是按照c語句逐句翻譯的,而是分開為兩個指令模組來實現的!

case 0: 

printf("a>0"); 

00411a83  push        offset string "a>0"  (4240dch)  

00411a88  call          @ilt+1300(_printf) (411519h)  

00411a8d  add         esp,4  

case 1: 

default: 

printf("a>10 && a<100"); 

00411a9f  push        offset string "a>10 && c<100" (424288h)  

00411aa4  call          @ilt+1300(_printf) (411519h)  

00411aa9  add         esp,4  

} 至於case 和 default分支中,如果有break,則會增加乙個無條件跳轉彙編指令。若沒有break,則就沒有任何迴圈控制**。 

小結:如果在反彙編**中發現連續多個「比較cmp」和「相等跳轉je」就會讓人聯想到「switch」語句了!

從彙編來看c語言

一 學習過程從c 語言的角度提出一些問題,這些問題再從彙編的角度考慮,還真的很有意思。1 我們用高階語言程式設計時,一般不可能不用到變數,但是一定要用到變數嗎?還有這些變數從彙編的角度是怎麼實現的呢?畢竟暫存器和記憶體空間是不可能儲存乙個變化的值的,要改變暫存器和記憶體空間的值,只有重新賦值。但是原...

從機器語言到組合語言

機器語言是計算機唯一能接受和執行的語言。機器語言由二進位製碼組成,每一串二進位製碼叫做一條指令。一條指令規定了計算機執行的乙個動作。一台計算機所能懂得的指令的全體,叫做這個計算機的指令系統。不同型號的計算機的指令系統不同。指令通常由幾個位元組組成,第乙個位元組是操作碼,它規定了計算機要執行的基本操作...

從C語言到C 語言

c 讀作 c加加 是 c plus plus 的簡稱。顧名思義,c 是在c語言 的基礎上增加新特性。從語法上看,c語言是 c 的一部分,c語言 幾乎不用修改就能夠以 c 的方式編譯。對於c和c 的關係,有很多種說法,新人很容易認為c 是c的公升級版,c 比c要高階,c 高大上,c過時了,這種想法不一...