函数调用约定

1. c调用约定 _cdecl

调用方将参数从右面到左压栈,被调用函数完成后,调用方负责从栈中清除参数。

// c代码
void sum(int a, int b);
int main() {
  sum(10, 20);
}
// 汇编代码
push 20
push 10
call sum
add esp 8
// 或者 编译器预先在栈顶分配了存储空间 
mov [esp + 4], 20
mov [esp], 10
call sum 
这种方式调用sum之后 不需要调整栈指针,GUN(g++和gcc)采用这个技巧。

2. stdcall 调用约定

参数压栈顺序跟cdel一样,只是恢复esp是在被调用者内进行,被调用这采用ret指令。
这种方式的有点是:生成的程序体积稍小 速度稍快, 但是缺点是:对于可变参数的方法不能采用这种方式,只能使用cdecl。

3. fastcall 调用约定

mov edx 20
mov ecx 10
call sum

fastcall是stdcall的变体, 区别是fastcall会使用ecx和edx保存前两个参数。fastcall负责清理esp, 返回的大小减去ecx和edx的大小。

4. c++调用约定

c++静态成员函数就不需要写了,因为他跟普通函数没有区别。
非静态成员函数调用约定,因为需要一个this指针,这个各家编译器有自己的实现,vs系列把this放到ecx里,GUN系列把this作为第一个隐藏参数,this被放到栈顶。

你可能感兴趣的:(函数调用约定)