調用約定決定:參數入棧順序、誰負責清理棧、函數名修飾規則。常見約定對比:
| 約定 | 關鍵字 | 參數入棧 | 棧清理者 | 名字修飾 (C) | 名字修飾 (C++) | 適用場景 |
|---|---|---|---|---|---|---|
| __stdcall | __stdcall / WINAPI | 右→左 | 被調用者 | _Func@N | ?Func@@YG...@Z | Win32 API、COM、回調函數 |
| __cdecl | __cdecl | 右→左 | 調用者 | _Func | ?Func@@YA...@Z | C/C++ 默認、可變參數函數 |
| __fastcall | __fastcall | 前兩個 DWORD 用 ECX/EDX,其餘右→左入棧 | 被調用者 | @Func@N | ?Func@@YI...@Z | 高性能需求、編譯器優化 |
| thiscall | (隱式) | this 指針在 ECX,參數右→左 | 調用者 | N/A | ?Func@@QA...@Z | C++ 非靜態成員函數 |
| naked call | __declspec(naked) | 由程序員手寫序言/結語 | 程序員 | 無修飾 | 無修飾 | 裸機編程、中斷處理、Hook |
WINAPI 宏在 Windows.h 中定義為 __stdcall,編寫自定義 API 時建議使用。/Gd (__cdecl)。可在項目屬性 C/C++ → Code Generation → Calling Convention 修改,或函數級指定關鍵字(優先級高於項目設置)。/Gz (__stdcall)、/Gd (__cdecl)、/Gr (__fastcall)。修飾名由 函數名、類名、調用約定、返回類型、參數類型/順序 共同決定。C++ 重載、模板、命名空間極大增加了修飾複雜度。
__stdcall:_FunctionName@ByteCount(如 _Add@8)__cdecl:_FunctionName(僅前綴下劃線)__fastcall:@FunctionName@ByteCount(前綴 @)格式:?FunctionName@@[修飾碼]
? 標識函數名開始。@@YG:__stdcall 全局/靜態函數@@YA:__cdecl 全局/靜態函數@@YI:__fastcall 全局/靜態函數@@QA、@@AA 等(thiscall 相關)。| 代碼 | 類型 |
| X | void |
| D | char |
| E | unsigned char |
| F | short |
| H | int |
| I | unsigned int |
| J | long |
| K | unsigned long |
| M | float |
| N | double |
| _N | bool |
| PA | 指針前綴,後跟指向類型代碼 |
| 0 | 重複類型標記(節省空間) |
@Z(有參數)或 Z(無參數)。查看修飾名工具
DUMPBIN /SYMBOLS file.objDUMPBIN /EXPORTS file.dll.map 文件(/MAP 選項)。