大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> 程序开发 -> Visual C++中函数调用方式浅探

Visual C++中函数调用方式浅探

时间: 2021-07-31 作者:daque

咱们领会在举行因变量挪用时,有几种挪用本领,分为c式,pascal式。在c和c++中c式挪用是缺省的,只有特出证明。二者是有辨别的,底下咱们用范例证明一下: 1. __cdecl :c和c++缺省挪用办法  例子: void input( int &m,int &n);/*十分于void __cdecl input(int &m,int &n);*/   以次是相映的汇编代码:   00401068   lea         eax,[ebp-8] ;取[ebp-8]地方(ebp-8),存到eax   0040106b   push        eax         ;而后压栈   0040106c   lea         ecx,[ebp-4] ;取[ebp-4]地方(ebp-4),存到ecx   0040106f   push        ecx         ;而后压栈   00401070   call        @ilt+5(input) (0040100a);而后挪用input因变量   00401075   add         esp,8       ;回复栈     从之上挪用input因变量的进程不妨看出:在挪用此因变量之前,开始压栈ebp-8,而后压栈ebp-4,而后挪用因变量input,结果input因变量挪用中断后,运用esp+8回复栈。由此看来,在c谈话挪用中默许的因变量化装_cdecl,由主挪用因变量举行参数压栈而且回复仓库。  底下看一下:地方ebp-8和ebp-4是什么?  在vc的view下选debug windows,而后选registers,表露存放器变量值,而后在选debug windows底下的memory,输出ebp-8的值和ebp-4的值(或径直输出ebp-8和-4),看一下这两个地方本质保存的是什么值,本质上是变量 n 的地方(ebp-8),m的地方(ebp-4),由此不妨看出:在主挪用因变量中举行实参的压栈而且程序是从右到左。其余,因为实参是相映的变量的援用,也表明本质上援用传播的是变量的地方(一致南针)。 归纳:在c或c++谈话挪用中默许的因变量化装_cdecl,由主挪用因变量举行参数压栈而且回复仓库,实参的压栈程序是从右到左,结果由降调因变量举行仓库回复。因为主挪用因变量处置仓库,以是不妨实行变参因变量。其余,定名化装本领是在因变量前加一个下划线(_).  2. winapi (本质上即是pascal,callback,_stdcall)  例子: void winapi input( int &m,int &n); 看一下相映挪用的汇编代码: 00401068   lea         eax,[ebp-8] 0040106b   push        eax 0040106c   lea         ecx,[ebp-4] 0040106f   push        ecx 00401070   call        @ilt+5(input) (0040100a)    从之上挪用input因变量的进程不妨看出:在挪用此因变量之前,开始压栈ebp-8,而后压栈ebp-4,而后挪用因变量input,在挪用因变量input之后,没有相映的仓库回复处事(为其它的因变量挪用,以是我没有列出)    底下再列出input因变量自己的汇编代码:(本质此因变量不大,但做汇编例子仍旧大了些,大师不妨只看前和后,中央代码与此例子无干)39: void winapi input( int &m,int &n)40:   {00401110   push        ebp00401111   mov         ebp,esp00401113   sub         esp,48h00401116   push        ebx00401117   push        esi00401118   push        edi00401119   lea         edi,[ebp-48h]0040111c   mov         ecx,12h00401121   mov         eax,0cccccccch00401126   rep stos    dword ptr [edi]41:       int s,i;42:43:       while(1)00401128   mov         eax,10040112d   test        eax,eax0040112f   je          input+0c1h (004011d1)44:       {45:       printf("\nplease input the first number m:");00401135   push        offset string "\nplease input the first number m"... (004260b8)0040113a   call        printf (00401530)0040113f   add         esp,446:       scanf("%d",&m);00401142   mov         ecx,dword ptr [ebp+8]00401145   push        ecx00401146   push        offset string "%d" (004260b4)0040114b   call        scanf (004015f0)00401150   add         esp,847:48:       if ( m<1 ) continue;00401153   mov         edx,dword ptr [ebp+8]00401156   cmp         dword ptr [edx],100401159   jge         input+4dh (0040115d)0040115b   jmp         input+18h (00401128)49:       printf("\nplease input the first number n:");0040115d   push        offset string "\nplease input the first number n"... (0042608c)00401162   call        printf (00401530)00401167   add         esp,450:       scanf("%d",&n);0040116a   mov         eax,dword ptr [ebp+0ch]0040116d   push        eax0040116e   push        offset string "%d" (004260b4)00401173   call        scanf (004015f0)00401178   add         esp,851:52:       if ( n<1 ) continue;0040117b   mov         ecx,dword ptr [ebp+0ch]0040117e   cmp         dword ptr [ecx],100401181   jge         input+75h (00401185)00401183   jmp         input+18h (00401128)53:54:       for(i=1,s=0;i<=n;i++)00401185   mov         dword ptr [ebp-8],10040118c   mov         dword ptr [ebp-4],000401193   jmp         input+8eh (0040119e)00401195   mov         edx,dword ptr [ebp-8]00401198   add         edx,10040119b   mov         dword ptr [ebp-8],edx0040119e   mov         eax,dword ptr [ebp+0ch]004011a1   mov         ecx,dword ptr [ebp-8]004011a4   cmp         ecx,dword ptr [eax]004011a6   jg          input+0a3h (004011b3)55:           s=s+i;004011a8   mov         edx,dword ptr [ebp-4]004011ab   add         edx,dword ptr [ebp-8]004011ae   mov         dword ptr [ebp-4],edx004011b1   jmp         input+85h (00401195)56:       if ( m >= s )004011b3   mov         eax,dword ptr [ebp+8]004011b6   mov         ecx,dword ptr [eax]004011b8   cmp         ecx,dword ptr [ebp-4]004011bb   jl          input+0afh (004011bf)57:           break;004011bd   jmp         input+0c1h (004011d1)58:       else59:           printf(" m < n*(n+1)/2,please input again!\n");004011bf   push        offset string " m < n*(n+1)/2,please input agai"... (00426060)004011c4   call        printf (00401530)004011c9   add         esp,460:       }004011cc   jmp         input+18h (00401128)61:62:   }004011d1   pop         edi004011d2   pop         esi004011d3   pop         ebx004011d4   add         esp,48h004011d7   cmp         ebp,esp004011d9   call        __chkesp (004015b0)004011de   mov         esp,ebp004011e0   pop         ebp004011e1   ret         8结果,咱们看到在因变量结束局部,有ret 8,鲜明是回复仓库,因为在32位c++中,变量地方为4个字节(int也为4个字节),以是弹栈两个地方即8个字节。  由此不妨看出:在主挪用因变量中控制压栈,在被挪用因变量中控制回复仓库。所以不许实行变参因变量,由于被调因变量不许事前领会弹栈数目,但在降调因变量中是不妨做到的,由于参数数目由降调因变量决定。  底下再看一下,ebp-8和ebp-4这两个地方本质保存的是什么值,ebp-8地方保存的是n 的值,ebp -4保存的是m的值。证明也是从右到左压栈,举行参数传播。   归纳:在主挪用因变量中控制压栈,在被挪用因变量中控制弹出仓库中的参数,而且控制回复仓库。所以不许实行变参因变量,参数传播是从右到左。其余,定名化装本领是在因变量前加一个下划线(_),在因变量名后有标记(@),在@反面跟不上参数列表中的参数所占字节数(10进制),如:void input(int &m,int &n),被化装成:_input@8   对于大普遍api因变量以及窗口动静处置因变量皆用 callback ,以是挪用前,降调因变量会先压栈,而后api因变量本人回复仓库。      如:      push edx      push edi      push eax      push ebx      call getdlgitemtexta   你不妨想一下,这几个存放器中存的都是什么?参考:msdn例子为在vc6.0下debug形式下的win32 console反汇编代码。

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.