1.64、什么是函数调用约定?

核心内容包括:

  • • 参数传递顺序:通常是参数从右向左依次入栈,也有部分调用约定使用寄存器传参。
  • • 堆栈清理者:调用结束后由调用者还是被调用者负责恢复堆栈。
  • • 返回值传递:一般通过寄存器(如EAX)传递。
  • • 函数名修饰:编译器根据调用约定对函数名进行不同的修饰,支持重载和避免冲突。

常见调用约定及其特点

调用约定 参数传递方式 栈清理者 特点及适用场景 函数名修饰示例
__cdecl 参数从右向左依次入栈 调用者清理(手动清栈) C/C++默认调用约定,支持可变参数函数(如printf) 函数名前加“_”,如_func
__stdcall 参数从右向左依次入栈 被调用者清理(自动清栈) Windows API默认调用约定,参数个数固定 函数名前加“_”,后加“@参数字节数”,如_func@8
__fastcall 前两个DWORD或更小参数通过ECX和EDX寄存器传递,其余参数从右向左入栈 被调用者清理 性能优化调用,适用于对速度要求较高的函数 函数名前加“@”,后加“@参数字节数”,如@func@8
__thiscall 参数从右向左入栈,this指针通过ECX寄存器传递(参数个数不确定时this指针也入栈) 参数个数确定时被调用者清理,不确定时调用者清理 C++非静态成员函数默认调用约定,特殊处理this指针 无显式关键字,函数名修饰依编译器而定
__pascal 参数从左向右入栈 被调用者清理 已废弃,历史遗留调用约定 -

总结

函数调用约定是函数调用过程中的“规则手册”,它决定了参数如何传递(寄存器还是堆栈)、参数入栈顺序、堆栈由谁清理以及函数名如何修饰。不同调用约定影响函数的性能、兼容性和可变参数支持,理解它们对于编写高效、稳定的C++程序和进行底层调试至关重要。

  • • __cdecl灵活,支持可变参数,但调用者负责清理堆栈,生成的代码稍大。
  • • __stdcall调用者简洁,适合固定参数的系统API,自动清理堆栈。
  • • __fastcall通过寄存器传递部分参数,提升调用效率,适合性能敏感场景。
  • • __thiscall专为C++成员函数设计,处理this指针传递。
    本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
    (加入我的知识星球,免费获取账号,解锁所有文章。)
阅读剩余
THE END