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

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

本週學習了彙編指令以及通過反彙編一個小程式來了解棧的變化
寫了一個簡單的C程式,如圖所示:

通過gcc -s -o main.s main.c -m32指令將其編譯成彙編程式
開啟該彙編檔案並刪除不重要的資訊,如圖所示:

分析該彙編指令(為了方便直接用手寫畫圖,為了區分不同時期的暫存器,將其後面加了個括號,括號裡的數字表示該暫存器的第幾種狀態)
如圖所示:

首先執行main函式
pushl %ebp :將esp的值減4(指向下一幀棧地址),並將ebp暫存器裡的值存入esp此時指向的棧地址。
Movl %esp, %ebp :將ebp暫存器同樣指向esp暫存器指向的那塊棧地址。
Sub $16, %esp :將esp暫存器的內容減16,即向下移動四個幀。
movl $1, -12(%ebp) : 將變址地址-12(%ebp)存入立即數1
movl $8, -8(%ebp) :將變址地址-8(%ebp)中存入立即數8
pushl -8(%ebp) : 將上述變址地址中的內容8壓入棧內。
pushl -12(%ebp) :同樣將上述變址地址中的內容1壓入棧內。
call g : 即呼叫g子函式,可分為 pushl eip(儲存call g的下一條指令即addl $8, %esp的地址)和 movl g, eip。
執行 g 子函式:
pushl %ebp : 將ebp的值壓入棧內。
movl %esp, %ebp : 將ebp暫存器也指向esp所指示的位置。
movl 8(%ebp), %edx : 將8(%ebp)中的內容1存入edx暫存器中
movl 12(%ebp), %eax : 將12(%ebp)中的內容存入eax暫存器中
addl %edx, %eax : 將edx和eax中的內容相加並存入eax暫存器當中
popl %ebp : 將esp暫存器的內容加四,即向上移動一幀,將pop出的內容賦值給ebp, ebp指向之前ebp所指的位置
如新圖所示:

ret : ret指令分為popl eip 和將eip暫存器存入儲存的call指令的下條指令即 add.......
addl $8, %esp : 將esp暫存器向上移動兩幀。
movl %eax, -4(%ebp) : 將eax的值9賦給-4(%ebp)的位置
movl -4(%ebp), %eax : 再從那個位置賦值給eax暫存器,(之所以那麼繞,我認為是因為在C語言裡我定義了一個變數c來得到g函式的返回值)
leave : 可分為 movl %ebp, %esp 和 popl ebp 即將esp指向ebp所指的位置,並將ebp以下的指令彈出,相當於清空棧。

小結:
在藍墨雲課堂以及庖丁解牛課本上上學習了基礎彙編指令,相關暫存器的用法,多種定址方式,對本科所學計算機組成原理的知識有了系統性的回顧。並學會了反彙編一個小程式,對計算機的棧操作有了基本的瞭解。
但是在gcc測驗裡遇到了一些問題,後來發現是指令細節把握不夠到位,也讓我意識到自己對Linux的基礎指令理解還不夠深刻。