從CPU執行計算機指令層面來看if...else和switch的區別

基礎概念:
  • 程序的執行過程:程序(高級語言寫的代碼)-- 彙編語言 – 到機器語言(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更優。有問題歡迎評論溝通!繼續努力!

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