基礎概念:
- 程序的執行過程:程序(高級語言寫的代碼)-- 彙編語言 – 到機器語言(CPU可識別的機器代碼)
- 相關彙編語言詞彙解釋:
mov
:賦值操作,例:mov DWORD PTR [rbp-0x4],0x1;
jne
: (jump if not equal 如果不等於就跳轉),例:jne 4a <main+0x4a>
jmp
: (jump)跳轉,例:jmp 51 <main+0x51>
je
:(jump if equal 如果等於則跳轉),例:je 4a <main+0x4a>
cmp
:(compare 比較),例:DWORD PTR [rbp-0x4],0x0
簡單熟悉
我們以c語言代碼爲例,我們先熟悉一下分析流程:
// test.c
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int r = rand() % 2;
int a = 10;
if (r == 0)
{
a = 1;
} else {
a = 2;
}
}
通過一下命令將代碼轉化爲彙編代碼,並打印出來:
$ gcc -g -c test.c
$ objdump -d -M intel -S test.o
//其中左邊的數字是機器代碼,顯然不是給人看的。右邊是彙編代碼,是給程序員看的,我們跟着序號看
if (r == 0)
3b: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0 //1.比較[rbp-ox4]和0x0,如果相等則將零標誌條件碼設置爲1,反之爲0
//DWORD PTR 代表操作的數據類型是 32 位的整數。[rbp-ox4]表示r變量的內存地址
3f: 75 09 jne 4a <main+0x4a> //2.判斷零標誌條件碼的結果,如果不是1則跳轉到4a(在最左側,代表行數),加載4a的地址的指令到CPU開始執行
{
a = 1;
41: c7 45 f8 01 00 00 00 mov DWORD PTR [rbp-0x8],0x1 //3.如果在第2步沒有跳轉,那麼將執行到這裏。把0x1賦值給[rbp-0x8]地址代表的變量a
48: eb 07 jmp 51 <main+0x51> //4.直接跳到51代表的行
}
else
{
a = 2;
4a: c7 45 f8 02 00 00 00 mov DWORD PTR [rbp-0x8],0x2 //5.把0x2賦值給[rbp-0x8]地址代表的變量a
51: b8 00 00 00 00 mov eax,0x0 //6.結束,繼續往下執行
}
注:我們回過頭去看前面的 if 條件,如果滿足的話,在賦值的 mov 指令執行完成之後,有一個 jmp
的無條件跳轉指令。跳轉的地址就是這一行的地址 51。我們的 main 函數沒有設定返回值,而 mov eax, 0x0 其實就是給 main
函數生成了一個默認的爲 0 的返回值到累加器裏面。if 條件裏面的內容執行完成之後也會跳轉到這裏,和 else
裏的內容結束之後的位置是一樣的。
分析if…else和switch:
相比到這裏,大家應該已經具備彙編語言的閱讀能力了,可以嘗試自己分析一下!
2段代碼如下:
轉化成彙編代碼如下:
由於博主比較懶,大家就自己分析一下吧,希望大家能分析出來爲什麼我們在寫代碼的時候,3層判斷以內if…else比switch優秀,大於3層的時候,則switch更優。有問題歡迎評論溝通!繼續努力!