您的位置:首页 > 其它

__cdecl __stdcall __fastcall 转载

2016-05-24 20:25 211 查看
Directive Parameter order Clean-up Passes parameters in registers?

register Left-to-right Routine Yes

pascal Left-to-right Routine No

cdecl Right-to-left Caller No

stdcall Right-to-left Routine No

safecall Right-to-left Routine No

调用约定 压参数入栈顺序 把参数弹出栈者 函数修饰名

(Calling convention)

__cdecl 右->左 调用者 _function

__fastcall 右->左 被调用者 @function@nnn

__stdcall 右->左 被调用者 _function@nnn

__pascal 左->右 被调用者 _function@nnn

__cdecl是C/C++和MFC程序默认使用的调用约定,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。

__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。

__fastcall约定用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。__fastcall可以写成_fastcall。

·特别说明

1. 在默认情况下,采用__cdecl方式,因此可以省略.

2. WINAPI一般用于修饰动态链接库中导出函数

3. CALLBACK仅用于修饰回调函数

便于更好理解, 看下面例子(函数调用的过程以汇编代码表示):

void cdecl fun1(int x,int y);

void stdcall fun2(int x,int y);

void pascal fun3(int x,int y);

void cdecl fun1(int x,int y);

fun1(x,y);

调用 fun1 的汇编代码

push y

push x

call fun1

add sp,sizeof(x)+sizeof(y) ;跳过参数区(x,y)

fun1 的汇编代码:

fun1 proc

push bp

mov bp,sp

……



pop bp

ret ;返回,但不跳过参数区

fun1 endp

void stdcall fun2(int x,int y);

fun2(x,y);

调用 fun2 的汇编代码

push y

push x

call fun2

fun2 的汇编代码:

fun2 proc

push bp

mov bp,sp

……



pop bp

ret sizeof(x)+sizeof(y) ;返回并跳过参数区(x,y)

fun2 endp

void pascal fun3(int x,int y);

fun3(x,y);

调用 fun3 的汇编代码

push x

push y

call fun3

fun3 的汇编代码:

fun3 proc

push bp

mov bp,sp

……



pop bp

ret sizeof(x)+sizeof(y) ;返回并跳过参数区(x,y)

fun3 endp
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: