一、函式呼叫堆疊
認真體會每一行指令位址!!!
#include
intsum(int a, int b)
//mov ebp,esp 讓esp回退到ebp的位置,回退棧幀的過程中,沒有對棧幀中的值進行清0的操作
//pop ebp 出棧並把出棧的值賦給ebp
int main()
下圖為上面示例函式,程式在sum函式中,棧的記憶體布局情況:
二、函式的返回值:
<=4byte eax
<4 <=8 eax,edx
8 產生臨時量驗證返回值小於等於8位元組的時候,返回值是怎麼帶回去的:
#include
typedef struct data
data;
data
sum(data a, data b)
; tmp.a = a.a + b.a;
return tmp;
}int main()
; data b = ;
data ret = ;
ret =
sum(a,b);
return
0;}
以上**在sum返回時,對應的彙編指令為:
return
tmp;
008c16cd
moveax,dword
ptr[tmp]
008c16d0
movedx,dword
ptr[ebp-0ch]
所以,大於4位元組,小於等於8位元組的函式返回值是由兩個暫存器eax、edx返回給呼叫方的;
那麼大於8位元組的呢???
函式產生臨時量的三種情況:
<1>函式呼叫之前;
<2>函式呼叫return的時候;
<3>函式呼叫接受返回值的時候,當呼叫函式的時候,需要判斷返回值是否大於8位元組,如果大於,那麼就需要傳入呼叫方的一塊臨時量位址,所以這個時候已經產生臨時量了;
驗證返回值大於8位元組的時候,返回值是怎麼帶回去的:
#include
typedef struct data
data;
data
sum(data a, data b)
; tmp.a = a.a + b.a;
return tmp;
}int main()
; data b = ;
data ret = ;
ret =
sum(a,b);
return
0;}
以下為呼叫sum是,產生的臨時變數:
ret = sum(a,b);
012f1785 sub esp,0ch //把變數b的值拷貝乙份,作為sum的引數
012f1788 mov eax,esp
012f178a mov ecx,dword ptr [b]
012f178d mov dword ptr [eax],ecx
012f178f mov edx,dword ptr [ebp-24h]
012f1792 mov dword ptr [eax+4],edx
012f1795 mov ecx,dword ptr [ebp-20h]
012f1798 mov dword ptr [eax+8],ecx
012f179b sub esp,0ch //拷貝a的值,作為sum的形參
012f179e mov edx,esp
012f17a0 mov eax,dword ptr [a]
012f17a3 mov dword ptr [edx],eax
012f17a5 mov ecx,dword ptr [ebp-10h]
012f17a8 mov dword ptr [edx+4],ecx
012f17ab mov eax,dword ptr [ebp-0ch]
012f17ae mov dword ptr [edx+8],eax
012f17b1 lea ecx,[ebp-124h]//由於返回值大於8位元組,所以在main的棧空間中開闢一塊臨時量位址,壓入sum的棧中;
012f17b7 push ecx
012f17b8 call sum (012f108ch)
當sum函式返回的時候,將sum中的區域性變數的值,拷貝到了ebp+8的地方,這是main函式中臨時量的記憶體位址;
return tmp;
012f16d0 mov eax,dword ptr [ebp+8]
012f16d3 mov ecx,dword ptr [tmp]
012f16d6 mov dword ptr [eax],ecx
012f16d8 mov edx,dword ptr [ebp-10h]
012f16db mov dword ptr [eax+4],edx
012f16de mov ecx,dword ptr [ebp-0ch]
012f16e1 mov dword ptr [eax+8],ecx
012f16e4 mov eax,dword ptr [ebp+8]
三、函式的呼叫約定_cdecl c呼叫約定
_stdcall windows標準的呼叫約定
_fastcall 快速呼叫約定
_thiscall c++成員函式的呼叫約定
呼叫約定影響函式的三個方面:
1、函式產生的符號名字不同;
2、函式引數入棧順序不同; 右—->左
3、誰來清理形參的記憶體;
_cdecl 由呼叫方開闢形參記憶體,呼叫方釋放形參記憶體;
_stdcall 呼叫方開闢形參記憶體,被呼叫方自己釋放形參記憶體;
_fastcall 呼叫方開闢形參記憶體,但是把最左邊(也就是最後的8個位元組通過兩個暫存器帶到被呼叫方的函式棧中)被呼叫方自己釋放形參記憶體;
函式呼叫堆疊
一 棧 1 傳統的棧 被定義為乙個特殊的容器,使用者可以將資料壓入棧中,也可以將壓入 棧中的資料彈出,但必須遵守一條規則 先進後出。2 計算機系統中的棧 是乙個有以上屬性的動態記憶體區域,壓棧操作使得棧增大,彈出操作使棧減小。棧通常是向下增長的。3 最重要的是棧儲存了乙個函式呼叫所需的維護資訊,這通...
函式呼叫堆疊
乙個函式的執行在棧上開闢記憶體。在函式呼叫時,第乙個進棧的是主函式呼叫語句的下一條可執行語句的位址,然後是函式的各個引數。在大多編譯器中,引數是由右往左入棧的,然後再是函式中的區域性變數。下面給乙個例項 int sum int a,int b int main 其中,main函式的反彙編指令 其中,...
函式呼叫堆疊
1.函式呼叫堆疊 壓棧 呼叫函式 1.壓入形參變數的位址和值 2.壓入函式呼叫返回後要執行的指令的位址 被呼叫函式 1.壓入呼叫函式的棧底指標,把棧底指標暫存器指向被呼叫函式的棧底 2.開闢被呼叫函式的棧幀大小,並初始化為cc 清棧 被呼叫函式 1.清理被呼叫函式開闢的棧幀大小 2.回退棧底指標到呼...