摘要
Calling conventions就是描述被调用代码的接口规则:
- 函数参数的分配顺序
- 参数如何传递(栈, 寄存器, 或两者混合)
- 寄存器的值由谁来维护(调用者或被调用者)
- 栈的准备和恢复分别由谁完成(调用者或被调用者)
调用者和被调用者
A函数调用(call)B函数, A是调用者, B是被调用者
调用者希望寄存器的值被保护, 这样在函数调用之间, 就不必费精力去保存/恢复寄存器的值. 而被调用者不希望寄存器的值被保护, 这样在函数进入时就不必保存寄存器的值, 函数退出的时候也不用恢复寄存器的值. 因此Calling Conventions的选择就是要平衡这个关系.
Calling Conventions
All
在32位x86下, EDI,ESI, EBP, EBX寄存器都是被保护的, EDX:EAX被用来存返回值
C (__cdecl)
参数由右向左入栈, 调用者清理参数, 函数名前加下划线修饰
__stdcall
WIN32编程中使用. 变参函数依然使用__cdecl. 参数由右向左入栈, 被调用者清理栈. 函数名修饰规则: _{function_name}@{bytes_of_parameters_taken}
__fastcall
前两个参数由ECX和EDX传递, 余下的从右向左由栈来传递. 被调用者清理栈. 函数名修饰规则: @{function_name}@{bytes_of_parameters_taken}
thiscall
第一个参数(就是this参数)由ECX传递, 余下的按照__stdcall来走. 被调用者清理栈. 函数名修饰规则由一个复杂的规则实现(为了实现C++的函数重载)