常见的几种调用约定

调用约定 参数压栈顺序 平衡堆栈
__cdecl(C Declaration的缩写)C语言中的默认调用约定 从右至左入栈 调用者清理堆栈
__stdcall 从右至左入栈 自身清理堆栈
__fastcall ECX/EDX传递前两个参数,剩下的从右至左入栈 自身清理堆栈

调用者清理堆栈就是外平栈,如下例中main函数调用完毕后恢复esp,自身清理堆栈则是在函数内部恢复esp后再返回,称之为内平栈,此例中一般使用ret 8指令,函数返回后不再对esp进行操作

1
2
3
4
5
    15:     method(1, 2);
00A918ED push 2
00A918EF push 1
00A918F1 call std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::_Sentry_base (0A91465h)
00A918F6 add esp,8

windows api一般都是__stdcall,如果要使用函数指针的话需要显式声明。
C语言中的main函数必须使用__cdecl约定