C的迴圈的反匯

2021-05-21 14:35:40 字數 4313 閱讀 2502

要從事「逆向工程」工作,或對其感興趣,請必然要接觸到組合語言。然而我們在對計算機語言的了解大都是從高階語言(如c、vb、dephi)開始的。那當我們閱讀由高階語言翻譯成的機器語言時肯定會遇到很多障礙。下面是我在看了相關書籍後,做的一些筆記,希望有點參考價值!

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

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**與機器反彙編**的關係了!

為了知識的完整性,這裡補充一下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 注釋末尾的反斜槓

今天用gcc編譯遇到如下警告 使用了 wall選項 warning multi line comment wcomment 導致警告的 是乙個函式宣告上面的注釋,如下 this arg is a driver,for example c and you can 查了下原來在注釋行的末尾加上反斜槓會導...

C基礎 strlen與sizeof的區別 彙總

關於 strlen 與 sizeof 的區別,我相信很多人都有所了解。以下我總結了幾點關於strlen 與 sizeof 的區別和注意事項。strlen sizeof 函式運算子 計算字串長度 計算型別所佔記憶體大小 執行結束時才計算出 編譯階段計算 引數只能是char 引數可以是型別也可以是cha...

C 迴圈的巢狀

迴圈巢狀 當迴圈語句中的迴圈體又是乙個迴圈語句時,就構成了 巢狀迴圈 巢狀層次 迴圈的巢狀層次從語法上沒有限制,但一般不超過三層,否則將影響可讀性。應用舉例 例2.16 列印九九表。列印格式為 1 2 3 4 5 6 7 8 9 1 12 2 4 3 3 6 9 9 9 18 27 36 45 54...