呼叫慣例規範函數呼叫時:參數壓堆順序、堆疊平衡由誰負責、暫存器使用、函數名稱修飾規則。決定了呼叫者與被呼叫者的二進位介面契約,跨語言、跨模組(DLL)互呼時必須一致。
| 慣例 | 關鍵字 | 參數壓堆順序 | 堆疊清理者 | 名稱修飾 (VC++) | 典型用途 |
|---|---|---|---|---|---|
| __stdcall | __stdcall / WINAPI | 右至左 | 被呼叫者 | _Func@N | Win32 API、COM、DLL 導出 |
| __cdecl | __cdecl (預設) | 右至左 | 呼叫者 | _Func | C/C++ 預設、可變參數函數 |
| __fastcall | __fastcall | 前兩個 DWORD 用 ECX/EDX,其餘右至左壓堆 | 被呼叫者 | @Func@N | 效能敏感路徑、Borland 編譯器預設 |
| thiscall | (隱含,非關鍵字) | this 在 ECX,其餘右至左壓堆 | 被呼叫者 | 依編譯器而異 | C++ 非靜態成員函數 |
| naked call | __declspec(naked) | 自定 | 自定 | 無修飾 | 裸機程式、中斷服務、手寫序言/結語 |
RET N 自動彈出參數,呼叫端無須調整 ESP。_FunctionName@參數總位元組數(如 _MyFunc@12)。WINAPI 在 Windows.h 定義為 __stdcall,建議所有 DLL 導出介面使用。printf),因呼叫者知道壓了多少參數。_FunctionName。__cdecl。ECX、EDX,減少記憶體存取。@FunctionName@N。__fastcall(關鍵字 __msfastcall 才對應 VC 風格)。this 指標固定放在 ECX,參數右至左壓堆。C++ 支援函數多載,編譯器會將函數簽章(類別、參數型別、呼叫慣例、回傳型別)編碼進修飾名稱。若需提供 C 相容介面(如 DLL 導出給 C 語言呼叫),必須加上 extern "C" 關閉修飾:
extern "C" __declspec(dllexport) void __stdcall MyAPI(int a);
此時匯出名稱即為原始 MyAPI,無修飾、無多載。
/Gd:預設 __cdecl/Gz:預設 __stdcall/Gr:預設 __fastcallextern "C" __stdcall(或 WINAPI),並提供 .def 檔或 __declspec(dllexport)。StdCall,參數型別對應 int→Int32、char*→StringBuilder/c_char_p。__fastcall,但需測量實際提升(現代編譯器優化極強,差異常微乎其微)。