Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24117
  • 博文数量: 13
  • 博客积分: 109
  • 博客等级: 民兵
  • 技术积分: 105
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-18 03:24
文章分类

全部博文(13)

文章存档

2012年(3)

2011年(10)

我的朋友

分类: WINDOWS

2012-03-24 01:49:11

调用约定

x86 calling conventions

用如下示例程序:

int fun(int a,int b)

{

return 0;

}

int main()

{

fun('\1','\2');

return 0;

}

C语言调用约定  (VC默认用的这个)

在声明函数时用__cdecl修饰,例如:int __cdecl fun(int a,int b)

fun('\1','\2');展成汇编代码如下:

push        2                      //从右至左,将参数推进堆栈                                                        

push        1                                                                                                        

call        @ILT+0(_fun) (00401005)//符号的形式为 下划线+函数名,当函数调用完函数以 ret 返回                         

add         esp,8                 //此时的堆栈和调用前的堆栈不一致,需要“调用者”恢复堆栈,用add指令将堆栈恢复平衡。

:c语言调用会在目标(Object)文件中产生一个符号代表这个函数,此符号的形式为 下划线+函数名,且函数以ret形式返回。

:CPU执行ret指令时,进行下面两步操作:(IP)=((SS)*16+(SP));(SP)=(SP)+2;

 

标准调用约定

__stdcall修饰,例如:int __stdcall fun(int a,int b)

fun('\1','\2');展成汇编代码如下:

00401068   push        2//从右至左                                                                                     

0040106A   push        1                                                                                               

0040106C   call        @ILT+0(_fun@8) (00401005) //符号的形式为 下划线+函数名+X,当函数调用完函数以 ret X返回(这里X为8)

//“调用者”不负责恢复堆栈。                                          

注:“别调用者”fun函数负责恢复堆栈,而“调用者”不需要恢复堆栈。这个是C语言调用和标准调用最重要的区别之一。

注: 符号的形式为 下划线+函数名+X。其中,X代表清理堆栈是需要的数字,函数以ret X形式返回。

CPU执行ret n 指令时 等效于(IP)=((SS)*16+(SP));(SP)=(SP)+2;(SP)=(SP)+n;

 

快速调用约定

__fastcall修饰,例如:int __fastcall fun(int a,int b)

fun('\1','\2');展成汇编代码如下:

00401078   mov         dl,2//从右至左,注意这里用的是mov,不是push,所以后面不用恢复堆栈。       

0040107A   mov         cl,1                                                                      

0040107C   call        @ILT+0(@fun@8) (00401005)//符号形式为 函数名+X 当函数调用完函数以ret返回。

 

C++类成员函数的调用约定thiscall

c++默认,不用修饰

fun('\1','\2');展成汇编代码如下:

00401068   push        2//从右至左                                                             

0040106A   push        1                                                                       

0040106C   call        @ILT+5(fun) (0040100a)//符号的形式为 函数名,当函数调用完函数以 ret 返回

00401071   add         esp,8                                                                   

 

 

 

附上MSDN上的解释:

以下代码为例:

void    calltype MyFunc( char c, short s, int i, double f );

...

void    MyFunc( char c, short s, int i, double f )

    {

    ...

    }

...

MyFunc ('x', 12, 8192, 2.7183);

例子代码的结果为:

__cdecl

The C decorated function name is "_MyFunc."

 

__stdcall and thiscall

The C decorated name (__stdcall) is "_MyFunc@20." The C++ decorated name is proprietary.

 

__fastcall

The C decorated name (__fastcall) is "@MyFunc@20." The C++ decorated name is proprietary.

 

 

阅读(820) | 评论(0) | 转发(0) |
0

上一篇:线程

下一篇:Linux网络编程之广播

给主人留下些什么吧!~~