欢迎来到天天文库
浏览记录
ID:40744181
大小:84.50 KB
页数:14页
时间:2019-08-07
《DLL中调用约定和名称修饰》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、DLL中调用约定和名称修饰调用约定(CallingConvention)是指在程序设计语言中为了实现函数调用而建立的一种协议。这种协议规定了该语言的函数中的参数传送方式、参数是否可变和由谁来处理堆栈等问题。不同的语言定义了不同的调用约定。 在C++中,为了允许操作符重载和函数重载,C++编译器往往按照某种规则改写每一个入口点的符号名,以便允许同一个名字(具有不同的参数类型或者是不同的作用域)有多个用法,而不会打破现有的基于C的链接器。这项技术通常被称为名称改编(NameMangling)或者名称修饰(NameDecoration)。许多C++编译器厂商选择了自己的名称修饰方案。 因此,
2、为了使其它语言编写的模块(如VisualBasic应用程序、Pascal或Fortran的应用程序等)可以调用C/C++编写的DLL的函数,必须使用正确的调用约定来导出函数,并且不要让编译器对要导出的函数进行任何名称修饰。一.调用约定(CallingConvention)调用约定用来处理决定函数参数传送时入栈和出栈的顺序(由调用者还是被调用者把参数弹出栈),以及编译器用来识别函数名称的名称修饰约定等问题。在MicrosoftVC++6.0中定义了下面几种调用约定,我们将结合汇编语言来一一分析它们:1、__cdecl__cdecl是C/C++和MFC程序默认使用的调用约定,也可以在函数声
3、明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。 下面将通过一个具体实例来分析__cdecl约定: 在VC++中新建一个Win32Console工程,命名为cdecl。其代码如下: int__cdeclAdd(inta,intb); //函数声明 voidmain(){ Add(1,2);
4、 //函数调用} int__cdeclAdd(inta,intb) //函数实现{ return(a+b);} 函数调用处反汇编代码如下: ;Add(1,2);push 2 ;参数从右到左入栈,先压入2push 1 ;压入1call @ILT+0(Add)(00401005) ;调用函数实现ad
5、d esp,8 ;由函数调用清栈2、__stdcall__stdcall调用约定用于调用Win32API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条retn指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。 还是那个例子,将__cdecl约定换成__stdcall: int__stdcallAdd(inta,intb){return(a+
6、b);} 函数调用处反汇编代码: ;Add(1,2);push 2 ;参数从右到左入栈,先压入2push 1 ;压入1call @ILT+10(Add)(0040100f) ;调用函数实现 函数实现部分的反汇编代码: ;int__stdcallAdd(inta,intb)push
7、 ebpmov ebp,espsub esp,40hpush ebxpush esipush edilea edi,[ebp-40h]mov ecx,10hmov eax,0CCCCCCCChrepstos dwordptr[edi];return(a+b);mov
此文档下载收益归作者所有