首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

呼叫慣例深度解析:__stdcall/__cdecl/__fastcall/thiscall 差異與應用

     編輯:關於C++

x86 Windows 平台四大呼叫慣例完整對比

呼叫慣例定義函數參數傳遞、堆疊清理、返回值放置、名稱修飾等規則,是跨模組/語言互操作的關鍵契約。

共同規範

  • 返回值:EAX (32位) / EDX:EAX (64位)
  • 被調用者保存暫存器:EDI, ESI, EBP, EBX (Callee-saved)

四大慣例詳細對比

慣例堆疊清理壓棧順序this 傳遞可變參數名稱修飾典型用途
__cdeclCaller右→左N/A✅ 支援_funcC/C++ 預設、printf 類
__stdcallCallee右→左N/A❌ 不支援_func@NWin32 API、COM、.NET P/Invoke 預設
__fastcallCallee右→左N/A❌ 不支援@func@N前兩個整數參數用 ECX/EDX
__thiscallCallee右→左ECX❌ 不支援編譯器相關C++ 非靜態成員函數

實戰反組譯驗證 (__stdcall)

int __stdcall Test(int a, char b, short c) { return a+c; }
main() { Test(5, 'a', 10); }

main 呼叫端:
  push 0Ah        ; 參數 3 (10)
  push 61h        ; 參數 2 ('a')
  push 5          ; 參數 1 (5)
  call Test
  mov [ebp-4], eax  ; 取得返回值,無額外堆疊清理指令

Test 內部結尾:
  ret 0Ch         ; Callee 清理 12 bytes (3 參數 × 4 bytes)

指定呼叫慣例的三種方式

  1. 函數宣告:int __stdcall Func(int);
  2. 編譯器開關 (MSVC):/Gd (__cdecl), /Gr (__fastcall), /Gz (__stdcall, C++ 預設)
  3. P/Invoke 屬性 (.NET):[DllImport(..., CallingConvention=CallingConvention.StdCall)]

常見錯誤與除錯

  • 慣例不匹配 → 堆疊損毀、參數錯位、崩潰
  • 回調函數未聲明正確慣例 (如 WINAPI 實為 __stdcall)
  • 只有公開符號時,理解慣例可從堆疊手動提取參數/返回值

64 位元統一

x64 (AMD64/IA64) 僅有一種呼叫慣例:前 4 個整數參數用 RCX, RDX, R8, R9,浮點用 XMM0-3,其餘入堆,Caller 清理,無慣例衝突問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved