调用约定总述

默认调用方式
VC默认方式__cdecl
Windows API默认方式__stdcall,
Delphi默认方式Register也就是_fastcall

如果用vc开发dll给其他语言用,则应该指定__stdcall方式。
堆栈由谁清除这个很重要,如果是要写汇编函数给C调用,一定要小心堆栈的清除工作,
如果是__cdecl方式的函数,则函数本身(如果不用汇编写)则不需要关心保存参数的堆栈的清除,
但是如果是__stdcall的规则,一定要在函数退出(ret)前恢复堆栈。

1.__cdecl
所谓的C调用规则。
参数调用顺序:按从右至左的顺序压参数入栈,由调用者把参数弹出栈。
堆栈清除: 对于传送参数的内存栈是由调用者来维护的。返回值在EAX中(**** 只有这个是调用函数自己维护堆栈 ****)
因此,对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候,仅在输出函数名前加上一个下划线前缀,格式为_functionname。

2.__stdcall
参数调用顺序:按从右至左的顺序压参数入栈,由被调用者把参数弹出栈。
堆栈清除: 函数自己在退出时清空堆栈,返回值在EAX中。 
__stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中, 
__stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12。

3.__fastcall(其实就是Delphi中默认的register调用方式)
参数调用顺序:寄存器传参(顺序是ECX,EDX,EAX三个寄存器),剩下的参数顺序自左向右压栈传送
堆栈清除: 函数自己在退出时清空堆栈,返回值在EAX中。
__fastcall调用的主要特点就是快,因为它是通过寄存器来传送参数的
a.分配寄存器:先用三个寄存器分配3个参数的空间,但是先不入参
b.多于3个参数入栈:多于3个参数时,先从左至右将参数依次入栈,见上面
c.寄存器入参:
(1)从右至左入参,顺序是ECX,EDX,EAX,见上面;
(2)如果总的参数不到三个,则优先使用顺序EAX,EDX,ECX寄存器,但是执行入参顺序还是ECX,EDX,EAX,例如两个参数时,使用EAX和EDX,而不是使用ECX和EDX,但是入参的顺序还是先EDX再EAX,正是因为这样所以Delphi对象的第一个参数self是在EAX中, Sender在Edx中,结论:使用寄存器的优先顺序是:EAX,EDX,ECX;寄存器入参的优先顺序是:ECX,EDX,EAX

4.__pascal
参数调用顺序:从左向右传递参数(**** 只有这个是从左到右,其他的都是从右到左 ****)
堆栈清除: 函数自己在退出时清空堆栈,返回值在EAX中

5.__thiscall
参数调用顺序:按从右至左的顺序压参数入栈
仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定

VC调用方式设置
调用约定可以通过工程设置:Setting…/C/C++ /Code Generation项进行选择,缺省状态为__cdecl。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值