結構化程式的乙個最基本的單元就是「函式」或者叫「過程」。在彙編這一層自然也相應的有支援這些概念的指令操作,如棧操作和棧幀的概念。
1、定址方式
我們已經知道在運算元表示中有一種是用來指示記憶體位址的內容的,在gnu assembly中指示記憶體位址有多種方式,這些方式被統稱「定址方式」。通用的定址格式為:「imm(eb, ei, s)」[1]。解釋一下:該表示式的計算方式為imm + r[eb] + r[ei] * s,這一串的結果是什麼呢?是乙個儲存器的位址,操作指令通過該運算元表示式計算出來的記憶體位址來訪問記憶體。
由通用形式演化幾種常見特殊形式如下:
1) imm - 注意與$imm區別,後者為立即數,而前者是以立即數形式承載的乙個記憶體位址,這種方式叫絕對定址;
2) (ex) - 注意與ex區別,後者為暫存器內容,而前者是以暫存器內容形式承載的乙個記憶體位址,這種方式叫間接定址;
3) imm(eb) - 其表示結果是記憶體位址為imm + r[eb];
4) (eb, ei) - 其表示結果是記憶體位址為r[eb] + r[ei];
5) imm((eb, ei) - 其表示結果是記憶體位址為imm + r[eb] + r[ei]。
2、暫存器使用
在「開啟彙編之門」中曾經提過雖然暫存器的專用性已經降低,但是某些暫存器還是有其專用場合的。gnu為我們制定了乙個暫存器使用規則,規則規定:「%eax、%ecx和%edx是由呼叫者負責儲存的,而%ebx、%ebi和%esi則由被呼叫者保護,而%esp和%ebp都是棧操作專用的」。
3、棧操作
棧,實際上是一塊兒專用的記憶體區域,每個程序位址空間都有其專有的棧區。地球人都知道關於棧有兩種操作:push和pop。相應的gnu assembly分別定義了「pushl s」和「popl d」分別來完成壓棧和出棧操作。每個操作都包含兩個步驟:移動棧頂指標和資料傳送。
pushl s <=> r[%esp] <-- r[%esp] - 4 ;m[r[%esp]]<-- s
popl d <=> d <-- m[r[%esp]];r[%esp] <-- r[%esp] + 4
4、棧幀的形成
提到函式或者過程呼叫就不能離開棧操作。而每個函式或者過程呼叫也都離不開乙個叫「棧幀」的概念。棧是用來傳遞引數、儲存返回結果等作用的,而棧幀則是1對1對映到某個過程呼叫的。棧幀由%ebp來標識。我們來看看乙個例子,通過該例子看看棧幀裡到底有些什麼東西?
void callee(int x, int y)
void caller(int m, int n)
+ +
| |
+----------+
| old %ebp | <--- %ebp
+----------+
| 本地變數 |
+----------+
| 引數n |
+----------+
| 引數...|
+----------+
| 引數1 |
+----------+
| 返回位址 |
+----------+
| ... |
| |<-- %esp
程式棧 棧幀
乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 棧區 stack 由編譯器自動分配釋放 存放函式的引數名,區域性變數的名等。其操作方式類似於資料結構中的棧。堆區 heap 由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os 注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶。靜...
Objective C指標 棧幀 棧
1 objective c的指標是用來只是物件的,例如 nsstring somestring the string 這種語法基本上是照搬c語言的,宣告了乙個名為somestring的變數,其型別為nsstring 也就是說此變數為指向nsstring的指標。所有objective c的物件都必須這...
彙編與棧幀學習(一)
最近學習 深入理解計算機系統 書中全是彙編,正好藉著gdb來研究一下組合語言和函式呼叫時棧幀的變化。於是寫下這個開篇的部落格,我先以乙個簡單的程式進行研究 如上圖這個程式 func.c 含有兩個函式。main和add,功能很簡單就是求兩個兩個數的和然後輸出。用命令 gcc func.c o func...