调用约定
概念
调用约定是关于被调用方和调用方的参数传递顺序、参数传递方式和堆栈的平衡方式
参数传递顺序:函数中的参数以何顺序存入堆栈或寄存器中
参数传递方式:将函数的参数压入堆栈或寄存器中存储
堆栈的平衡方式:调用方或被调用方谁将堆栈或寄存器中数据复制出来,然后清空堆栈或寄存器中的数据,以及在函数调用完成后还原堆栈或寄存器中的数据
常见的调用约定及其特性
常见的调用约定有:__cdecl、__fastcall、__stdcall、__thiscall
约定 | 传参顺序 | 传参方式 | 清理者 | 参数数量 |
---|---|---|---|---|
__cdecl | 由右到左 | 压栈 | 调用方 | 支持可变参数 |
__fastcall | 由右到左 | 寄存器/压栈 | 被调用方 | 不支持可变参数 |
__stdcall | 由右到左 | 压栈 | 被调用方 | 不支持可变参数 |
__thiscall | 由右到左 | 寄存器 | 调用方 | 支持可变参数 |
__cdecl
__cdecl是C语言默认的函数调用方法。 被调用函数在编译阶段对参数的数量无任何要求限制,并且由调用方来清理堆栈,所以实现了可变参数。
__fastcall
__fastcall将在尽可能的情况下使用寄存器传参,即将前两个参数(最大为DWORD型)通过寄存器传参。不同的编译器使用的寄存器不同,所以无法实现跨寄存器的接口。
__stdcall
__stdcall是绝大多数winapi所使用的调用约定。
__thiscall
__thiscall只由C++成员函数调用,__thiscall实际上是一个关于类的调用方式,是将类的每一个函数都加上一个this类指针,将这个this指针存放在ECX寄存器