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】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)
阅读剩余
版权声明:
作者:讳疾忌医-note
链接:https://www.1217zy.vip/archives/1415
文章版权归作者所有,未经允许请勿转载。
THE END