| 特性 | __cdecl (C/C++ 預設) | __stdcall (WINAPI/CALLBACK/類別成員) |
|---|---|---|
| 參數壓棧順序 | 右到左 | 右到左 |
| 棧平衡責任 | 呼叫者 | 被呼叫者 |
| 支援可變參數 | 是 | 否 |
| 名稱修飾 | 前綴 `_` | 前綴 `_` + 後綴 `@n` (位元組數) |
// void Input(int &m, int &n);
00401068 lea eax, [ebp-8] ; 取 n 位址
0040106B push eax ; 壓棧第 2 參數
0040106C lea ecx, [ebp-4] ; 取 m 位址
0040106F push ecx ; 壓棧第 1 參數
00401070 call @ILT+5(Input) ; 呼叫函數
00401075 add esp, 8 ; 呼叫者平衡棧 (2*4=8 位元組)
觀察記憶體:ebp-8 儲存 `n` 位址,ebp-4 儲存 `m` 位址,驗證「引用實為指標」且「右到左壓棧」。
// void WINAPI Input(int &m, int &n);
; 呼叫端相同壓棧序列
00401068 lea eax, [ebp-8]
0040106B push eax
0040106C lea ecx, [ebp-4]
0040106F push ecx
00401070 call @ILT+5(Input)
; 呼叫端無 add esp 指令!
; 函數內部結尾:
004011DE mov esp, ebp
004011E0 pop ebp
004011E1 ret 8 ; 被呼叫者以 ret 8 平衡棧
關鍵差異:ret 8 直接在返回指令完成棧平衡,呼叫端無需額外指令。這也是為何 __stdcall 不支援可變參數——被呼叫者無法預知參數總大小。
WINAPI/CALLBACK),確保二進位相容ebp-8、ebp-4 觀察實際參數內容call 後是否有 add esp, n 判斷呼叫慣例範例環境:VC6.0 Debug 模式 Win32 Console 專案反組譯碼。理解呼叫慣例是混合語言開發、DLL 介面設計、逆向分析的基礎功夫。