首先介紹幾個名詞:
棧幀:也叫過程活動記錄,是編譯器用來實現過程/函式呼叫的一種資料結構。棧幀中儲存了該函式的返回位址和區域性變數。
暫存器:cpu內部用來存放資料的一些小型儲存區域,用來暫時存放參與運算的資料和運算結果。常用的暫存器有:
esp:棧指標暫存器(extended stack pointer),其內存放著乙個指標,該指標永遠指向系統棧最上面乙個棧幀的棧頂。
ebp:基址指標暫存器(extended base pointer),其內存放著乙個指標,該指標永遠指向系統棧最上面乙個棧幀的底部。
eip:指令暫存器(extended instruction pointer),其內存放著乙個指標,該指標永遠指向下一條等待執行的指令位址。
eax:累加器(accumulator),一般用來儲存函式的返回值。
函式呼叫過程中系統棧的變化可見另一篇博文資料結構之—棧和遞迴&函式呼叫
下面具體講函式呼叫的步驟及組合語言中的相關指令。
函式呼叫大概包括以下幾個步驟:
引數入棧:將引數從從右向左依次壓入系統棧中。
**區跳**處理器從當前**區跳轉到被呼叫函式的入口處。
棧幀調整:具體包括
(1)儲存當前棧幀狀態值,以備後面恢復本棧幀時使用(ebp入棧);
(2)將當前棧幀切換到新棧幀(將esp值裝入ebp,更新棧幀底部);
(3)給新棧幀分配空間(把esp減去所需空間的大小,抬高棧頂);
以下附上《0day安全:軟體漏洞分析技術》書中相關配圖說明此過程
函式呼叫時用到的指令序列大致如下:
//....呼叫前
//呼叫開始
push 引數3
//假設函式有3個引數,將從右向左依次入棧
push 引數2
push 引數1
call 函式位址 //向棧中壓入當前指令在記憶體中的位置,即儲存返回位址;
//跳轉到所呼叫函式的入口位址函式入口處
push ebp //儲存舊棧幀的底部
mov ebp,esp //設定新棧幀的底部(棧幀切換)
sub esp,*** //設定新棧幀的頂部(抬高棧頂,為新棧幀開闢空間)
具體過程可參考下圖:
函式返回時的相關指令序列如下:
addesp,*** //降低棧頂,**當前的棧幀
pop ebp //將上乙個棧幀底部位置恢復到ebp
retn //彈出當前棧頂元素,即彈出棧幀中的返回位址,完成棧幀恢復工作
//讓處理器跳轉到彈出的返回位址,恢復呼叫前的**區
彙編看函式呼叫過程
分析下列原始碼 include dword stdcall function dword dwp1,pvoid p2 int main 轉彙編 vs2012 include dword stdcall function dword dwp1,pvoid p2 00fe1401 pop edi edi...
從彙編看,vc呼叫API函式和自定義函式的區別
api函式呼叫 是先得到api函式 位址的匯入位址,再得到api函式 位址,再執行 內部實現函式呼叫 是先調 內部實現函式 的 函式入口的靜態表 ilt 的對應函式,再執行真正函式 比如 調messageboxa null,test test mb ok 執行彙編 為 dword ptr imp m...
從彙編看c 內聯函式評估求值
在c 中,乙個inline函式實體,在整個class 宣告未被完全看到之前,是不會被評估求值的,也就是說,對於類裡面內聯的成員函式本身的分析,要等到class的宣告完全結束之後才開始。下面試c 原始碼 extern int x 外部宣告的x class x private float x 類自身的成...