1. 程式人生 > >《Linux核心原理與分析》第二週作業

《Linux核心原理與分析》第二週作業

反彙編一個簡單的C程式

1、實驗要求

使用:

gcc –S –o test.s test.c -m32

命令編譯成彙編程式碼,對彙編程式碼進行分析總結。其中test.c的具體內容如下:

int g(int x)
{
  return x + 3;
}

int f(int x)
{
  return g(x);
}

int main(void)
{
  return f(8) + 1;
}

2、實驗過程

  • 使用vim對test.c進行編輯,將上述程式碼鍵入
  • 使用gcc對test.c編譯,產生test.s檔案
gcc -S -o test.s test.c -m32

如下圖所示:

  • 使用vim檢視test.s檔案
    檢視test.s檔案,如下圖所示:

    “.”開通的所有程式碼為連結時候的輔助資訊,不會被實際執行,我們可以把這些程式碼刪除,刪除後的程式碼即為純淨的彙編程式碼,如下圖所示:

3、實驗分析

  • 彙編程式碼流程分析
    • 彙編程式碼依然從main函式讀起
      • eip暫存器從main函式起自+1,指向當前執行的指令語句(未遇到特殊指令時)
      • ebp暫存器始終指向棧底,esp暫存器始終指向棧頂,eax暫存器用來暫存一些數值(如函式的返回值)
      • ebp入棧
      • 把ebp值賦予給esp
      • 將esp值減4,指向下一棧儲存空間
      • 將數值2018存在esp所指的儲存空間中
    • 呼叫f函式
      • ebp入棧
      • 把ebp值賦予給esp
      • 將esp減4,指向下一棧地址空間
      • 將ebp變址定址8,即向上退兩個棧空間,並將此空間值賦給eax
      • 將eax的內容賦予給esp
    • 呼叫g函式
      • 對ebp進行壓棧
      • 把ebp值賦予給esp
      • 將ebp變址定址8,即向上退兩個棧空間,並將此空間值賦給eax
      • 將eax儲存的數值加9228
      • 出棧
      • 返回f函式call語句的下一句(leave)
    • 返回main函式
      • 返回main的call指令下一句(addl)
      • 將eax儲存的數加9228
      • esp指向ebp位置,ebp指向棧中指向的位置(leave作用)
      • 返回
  • 堆疊變化分析
    初始化狀態esp和ebp都在棧底:

    後指令程式碼從main函式順序執行:



    執行到call f指令,eip記錄call指令的下一條語句位置,此時程式碼跳轉至f函式執行:






    執行到call g指令,eip記錄call指令下一條語句位置,此時程式碼跳轉至g函式執行:




    此時,g函式執行到ret,返回f函式call的下一條語句leave:





    至此,整個指令執行完成,堆疊為空。

4、實驗總結

組合語言是計算機的低階語言,真正的深入瞭解組合語言對於我們深入理解計算機系統有著極大的幫助,更是為我們未來linux核心分析的深入學習打下堅實基礎。本次使用C語言反編譯成組合語言,利用我們熟悉的C語言程式碼來對照理解彙編指令程式碼、分析堆疊的變化讓我們更好的理解計算機在執行程式的時候是如何工作的。具體來說:

  • 加深了esp、ebp、eip以及eax各自作用的印象
  • 更好的理解了變址定址的具體過程
  • 更加熟悉了常用的彙編指令
  • 瞭解了計算機在執行程式時是如何工作的

其他問題

在進行makefile的測試時,在vim中寫好了Makefile,在進行make時,shell提示沒有找到make指令,我意識到應該是沒有內建此指令,便使用sudo apt-get install make獲取make指令,但shell提示:

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set

應該是賬戶的許可權不夠,但我想要切換到系統內建的root賬戶,要求我輸入密碼,但我好像並不知道root的密碼……
經過一系列的資料查詢,參考了此篇博文的方法,進入recovery模式更改root賬戶密碼。重啟後,使用root賬戶,sudo apt-get install make執行成功,make命令成功安裝。
出現這樣的小插曲,也算是在本次作業之外的一個小收穫。