关于函数调用约定的学习笔记

总体概述:

关于调用约定中,主要涉及的内容就是不同的调用约定对于函数调用栈平衡是由调用者维护栈平衡还是被调用者自己维护栈平衡、传入参数的方向从右到左还是从左到右通过栈传参还是通过寄存器传参、还有一个就是关于不同调用约定方式对于函数名的修饰方式。总体上了解这些就差不多了。

----------------------------------------------------------------------



调用者自己恢复栈平衡,用于可变参函数,调用约定为__cdecl,汇编代码表现
push 参数
call 函数
add esp,4




被调用者自己恢复栈平衡__stdcall
push 参数
call 函数




采用寄存器传参__fastcall
mov edx,参数
mov ecx,参数
call 函数


以上各种调用约定对应的编译器选项 /Gz (stdcall)、/Gr (fastcall)、/Gd (cdecl)


说明:在MSDN帮助文档中可以搜关键字__cdcel
----------------------------------------------------------------------
关于使用不同调用约定的C函数名修饰:
C 函数的修饰形式取决于其声明中使用的调用约定,如下所示。


调用约定              修饰
 
__cdecl(默认值)     前导下划线 (_)
 
__stdcall             前导下划线 (_) 和结尾 at 符 (@),后面跟表示参数列表中的字节数的数字
 
__fastcall            与 __stdcall 相同,但前置符不是下划线,而是 @ 符


实例分析:(自己动手实践验证VS2010)
函数原型:    修饰后的名称:
int __fastcall fun3(int a, int b);   @fun3@8
int __stdcall fun2(int a, int b);   _fun2@8
int __cdecl fun1(int a, int b);   _fun1




------------------------C++ 修饰名的格式----------------------------------------------
C++ 函数的修饰名包含下列信息:


函数名。


函数所属的类(如果函数是成员函数)。这可能包括封装函数的类的类,等等。


函数所属的命名空间(如果函数是某个命名空间的组成部分)。


函数的参数类型。


调用约定。


函数的返回类型。


函数名和类名在修饰名中以代码形式存在。修饰名的其余部分是仅对编译器和链接器具有内部意义的代码。下面是未修饰的和修饰的 C++ 名称的示例。


未修饰名 修饰名
 
int a(char){int i=3;return i;};        ?a@@YAHD@Z 
 
void __stdcall b::c(float){};          ?c@b@@AAGXM@Z 
 


------------Argument Passing and Naming Conventions---------------------------------
Microsoft Specific


All arguments are widened to 32 bits when they are passed. Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are pushed onto the stack from right to left. Structures that are not PODs will not be returned in registers.


The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they are used in the function.


Note: 
When a struct, union, or class is returned from a function by value, all definitions of the type need to be the same, else the program may fail at runtime.
 


For information on how to define your own function prolog and epilog code, see (Naked Function Calls).


The following calling conventions are supported by the Visual C/C++ compiler.


Keyword Stack cleanup Parameter passing
 
__cdecl Caller Pushes parameters on the stack, in reverse order (right to left)
 
__clrcall n/a Load parameters onto CLR expression stack in order (left to right).
 
__stdcall Callee Pushes parameters on the stack, in reverse order (right to left)
 
__fastcall Callee Stored in registers, then pushed on stack
 

__thiscall CalleePushed on stack; this pointer stored in ECX


最后补充一点就是关于调用约定在IPF处理器和X64处理器下的一些说明,以下引用自MSDN帮助手册中的原话:

On Itanium Processor Family (IPF) and x64 processors, __cdecl is accepted and ignored by the compiler; on IPF, by convention, parameters are passed in register. 

On Itanium Processor Family (IPF) and x64 processors, __stdcall is accepted and ignored by the compiler; on IPF, by convention, parameters are passed in register. 

On Itanium Processor Family (IPF) and AMD64 machines, __fastcall is accepted and ignored by the compiler; on an IPF chip, by convention, parameters are passed in register. 

主要说的就是在这两种处理直接采用寄存器传参方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值