当先锋百科网

首页 1 2 3 4 5 6 7

函数调用约定:当一个函数被调用时,函数的参数会被传递给被调用的函数和返回值会被返回给调用函数。函数的调用约定就是描述参数是怎么传递和由谁平衡堆栈的,当然还有返回值。

函数调用约定的主要约束事件: 

参数传递顺序:   

          1.从右到左依次入栈:__stdcall,__cdecl,__thiscall   

         2.从左到右依次入栈:__pascal,__fastcall(__简写为一个_)

清除栈:

   1.调用者清除栈。  

         2.被调用函数返回后清除栈。

在windows中,我们常用的两种调用约定就是:_cdecl &_stdcall,另外在vc中,_stdcall又被定义为:WINAPI CALLBACK

他们的压栈顺序都为从右到左,但是他们的清除栈者是不同的。_cdecl由调用者清除栈,而_stdcall由被调用者清除栈。他们的作用在哪呢?_cdecl主要用到变参函数,例如printf(),被调函数并不知道将来会有多少个参数,所以只能由调用者来清理堆栈;而_stdcall则用于定参数,他把处理权限交予被调函数,这样有利于跨平台;

 

下面主要看看这两种调用约定的区别:

#include <IOSTREAM>
using namespace std;
int _cdecl Add(int a,int b)
{
	return a+b;
}
int WINAPI Reduce(int a,int b)
{
	return a-b;
}
void main()
{
	int a=10 ,b=10;
	int result;
	result=Add(a,b);
	result=Reduce(a,b);
}


 

 

15:       result=Add(a,b);

004010C6   mov         eax,dword ptr [ebp-8]

004010C9   push        eax    //入栈

004010CA   mov         ecx,dword ptr [ebp-4]

004010CD   push        ecx    //入栈

004010CE   call        @ILT+0(Add) (00401005)

004010D3   add         esp,8  //清除栈

004010D6   mov         dword ptr [ebp-0Ch],eax

16:       result=Reduce(a,b);

004010D9   mov         edx,dword ptr [ebp-8]

004010DC   push        edx//入栈

004010DD   mov         eax,dword ptr [ebp-4]

004010E0   push        eax//入栈

004010E1   call        @ILT+20(Reduce) (00401019)

004010E6   mov         dword ptr [ebp-0Ch],eax

4:    {

00401040   push        ebp

00401041   mov         ebp,esp

00401043   sub         esp,40h

00401046   push        ebx

00401047   push        esi

00401048   push        edi

00401049   lea         edi,[ebp-40h]

0040104C   mov         ecx,10h

00401051   mov         eax,0CCCCCCCCh

00401056   rep stos    dword ptr [edi]

5:        return a+b;

00401058   mov         eax,dword ptr [ebp+8]

0040105B   add         eax,dword ptr [ebp+0Ch]

6:    }

0040105E   pop         edi

0040105F   pop         esi

00401060   pop         ebx

00401061   mov         esp,ebp

00401063   pop         ebp

00401064   ret//恢复指令地址

8:    {
00401070   push        ebp
00401071   mov         ebp,esp
00401073   sub         esp,40h
00401076   push        ebx
00401077   push        esi
00401078   push        edi
00401079   lea         edi,[ebp-40h]
0040107C   mov         ecx,10h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]
9:        return a-b;
00401088   mov         eax,dword ptr [ebp+8]
0040108B   sub         eax,dword ptr [ebp+0Ch]
10:   }
0040108E   pop         edi
0040108F   pop         esi
00401090   pop         ebx
00401091   mov         esp,ebp
00401093   pop         ebp
00401094   ret         8 //恢复指令地址和清理栈


//主要是想巩固一下自己的记忆