函数调用约定

参数传递过程中,二个问题:

1 当参数多于1个时,按照什么顺序把参数入栈

2 函数调用后 ,由谁把栈恢复原貌

函数调用时,函数调用者依次把参数压栈,然后调用函数,函数调用后,在栈中取得数据,并进行计算。函数调用结束后,

或者调用者或者函数本身修改栈,使栈恢复原貌。

 

stdcall

stdcall调用约定声明函数的格式:

int __stdcall func(int x, int y)

stdcall的调用约定规则:

参数入栈规则: 参数从右向左入栈

堆栈平衡:被调用函数自身修改栈

函数名自动加前导的下划线,后面紧跟一个@符合,其后紧跟着参数的尺寸。

 

 

cdecl调用约定

C语言缺省的调用约定,它声明函数的格式:

int func(int x, int y) 或 int __cdecl func(int x, int y)都可以

cdecl的调用约定规则:

参数入栈顺序: 从右到左

堆栈平衡:调用者修改栈

函数名:前加下划线

由于每次函数调用都要由编译器产生还原栈的代码,所以使用__cdecl方式编译的程序比使用__stdcall编译的程序大很多。

但是__cdecl调用方式是由函数调用者负责清除栈中的函数参数,所以这种方式支持可变参数,比如printf()和Windows API的wsprintf

 

fastcall调用约定
fastcall调用约定声明函数的格式:

int fastcall func(int x, int y)

fastcall调用约定规则:

参数入栈顺序:函数的第一个和第二个参数通过ecx和edx传递,剩余参数从右到左入栈

堆栈平衡:被调用者修改栈

函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸

以fastcall声明执行的函数,具有较快的执行速度,因为函数的前二个参数通过寄存器来传递的。

 

thiscall调用约定
thiscall是C++类成员函数缺省的调用约定,但它没有显示的声明形式。在C++类中,成员函数调用还有一个this指针参数,因此必须特殊处理,thiscall意味着:

参数入栈:参数从右向左入栈

this指针入栈:如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入栈。

栈恢复:对参数个数不定的,调用者清理栈,否则函数自己清理栈。

 

函数调用约定:


调用函数时使用的是绝对地址
c语言:
X86:_cdecl _stdcall _fastcall
X64:_fastcall
C++ thiscall: 将类的this指针的地址给寄存器 不压参

 

X86
_cdecl:回收参数列表由主调函数完成
stdcall:回收参数列表由被调函数完成 ret的作用—— 先pop eip 然后 esp 加(add) 一个值(回收参数列表)


fastcall:第一第二参数不压参,直接传递给寄存器 ecx edx 回收参数列表由被调函数完成


X64
fastcall: 多了r8 r9 两个寄存器 可以直接将前四个参数传递给寄存器(rcx rdx r8 r9)

posted @ 2020-03-28 08:31  坦坦荡荡  阅读(259)  评论(0编辑  收藏  举报