何为调用约定

调用约定指的是函数在调用时会按照不同规则,翻译成不同的汇编代码。这和参数的压栈顺序和栈的清理方式相关,也就是说不同的调用约定,这些方式会做相应改变。一般编译器是以默认的调用约定编译一份代码,但当一个项目使用不同调用约定的库会产生链接错误。

 
何为函数导出名
    同一个函数,在不同的编译器编译出来的符号名是不一样的,程序目标文件链接的时候不知道源程序的函数名,而是通过目标文件(.obj)中寻找相应的函数符号表。在下面中会指出不同调用约定对应的函数导出名。
 
三种调用约定
 
(1)__fastcall
特点:快
参数传递方式:前两个参数-寄存器,剩余参数-栈(右到左)
栈的清理者:被调函数
函数导出名:
按C的编译方式:@函数名@参数字节数
按C++的编译方式:
 
(2)__cdecl
特点:C语言调用约定,文件比__stdcall大
参数传递方式:栈(右到左)
栈的清理者:调用者
函数导出名:
按C的编译方式:_函数名
按C++的编译方式:规则同下面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。
(3)__stdcall
特点:标准调用约定,   Pascal程序的缺省调用方式,通常用于Win32 Api中
参数传递方式:栈(右到左)
栈的清理者:被调用者
函数导出名:
按C的编译方式:_函数名@参数字节数
按C++的编译方式:
1)、以"?"标识函数名的开始,后跟函数名;
2)、函数名后面以"@@YG"标识参数表的开始,后跟参数表;
3)、参数表以代号表示:
  X--void ,
  D--char,
  E--unsigned char,
  F--short,
  H--int,
  I--unsigned int,
  J--long,
  K--unsigned long,
  M--float,
  N--double,
  _N--bool,
  PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代表一次重复;
4)、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
5)、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。 
    上面这段代码,源文件后缀必须是.c,同时使用windows系统的dumpbin工具即可获得对应目标文件的内容。
 
    int __cdecl f1(int a)
{
return a +;
}
int __stdcall f2(int b)
{
return b +;
}
int __fastcall f3(int c)
{
return c +;
}
int main()
{
//函数导出名为_f1、_f2@4、@f3@4
int i = f1();
int j = f2();
int k = f3();
return0;
}
@f3@:
: push ebp
:8B EC mov ebp,esp
: EC CC sub esp,0CCh
: push ebx
0000000A: push esi
0000000B: push edi
0000000C: push ecx
0000000D:8D BD FF FF FF lea edi,[ebp+FFFFFF34h]
: B9 mov ecx,33h
: B8 CC CC CC CC mov eax,0CCCCCCCCh
0000001D: F3 AB rep stos dword ptr es:[edi]
0000001F: pop ecx
:894D F8 mov dword ptr [ebp-],ecx
:8B45 F8 mov eax,dword ptr [ebp-]
: C0 add eax,
:5F pop edi
0000002A:5E pop esi
0000002B:5B pop ebx
0000002C:8B E5 mov esp,ebp
0000002E:5D pop ebp
0000002F: C3 ret
_f1:
: push ebp
:8B EC mov ebp,esp
: EC C0 sub esp,0C0h
: push ebx
0000000A: push esi
0000000B: push edi
0000000C:8D BD FF FF FF lea edi,[ebp+FFFFFF40h]
: B9 mov ecx,30h
: B8 CC CC CC CC mov eax,0CCCCCCCCh
0000001C: F3 AB rep stos dword ptr es:[edi]
0000001E:8B4508 mov eax,dword ptr [ebp+]
: C0 add eax,
:5F pop edi
:5E pop esi
:5B pop ebx
:8B E5 mov esp,ebp
:5D pop ebp
0000002A: C3 ret
_f2@:
: push ebp
:8B EC mov ebp,esp
: EC C0 sub esp,0C0h
: push ebx
0000000A: push esi
0000000B: push edi
0000000C:8D BD FF FF FF lea edi,[ebp+FFFFFF40h]
: B9 mov ecx,30h
: B8 CC CC CC CC mov eax,0CCCCCCCCh
0000001C: F3 AB rep stos dword ptr es:[edi]
0000001E:8B4508 mov eax,dword ptr [ebp+]
: C0 add eax,
:5F pop edi
:5E pop esi
:5B pop ebx
:8B E5 mov esp,ebp
:5D pop ebp
0000002A: C2 ret
_main:
: push ebp
:8B EC mov ebp,esp
: EC E4 sub esp,0E4h
: push ebx
0000000A: push esi
0000000B: push edi
0000000C:8D BD 1C FF FF FF lea edi,[ebp-0E4h]
: B9 mov ecx,39h
: B8 CC CC CC CC mov eax,0CCCCCCCCh
0000001C: F3 AB rep stos dword ptr es:[edi]
0000001E:6A01 push
: E8 call _f1
: C4 add esp,
: F8 mov dword ptr [ebp-],eax
0000002B:6A02 push
0000002D: E8 call _f2@
: EC mov dword ptr [ebp-14h],eax
: B9 mov ecx,
0000003A: E8 call @f3@
0000003F: E0 mov dword ptr [ebp-20h],eax
: C0 xor eax,eax
:5F pop edi
:5E pop esi
:5B pop ebx
: C4 E4 add esp,0E4h
0000004D:3B EC cmp ebp,esp
0000004F: E8 call __RTC_CheckEsp
:8B E5 mov esp,ebp
:5D pop ebp
: C3 ret
 
相关命令是:
 //把获得obj函数导出名,存储到d:\\1.txt文件
dumpbin OBJ文件路径/all /rawdata:none > d:\\.txt //获得汇编代码,存储到d:\\2.txt
dumpbin OBJ文件路径/disasm d:\\.txt
    
C编译的函数如何在C++中使用
    解决办法是采用extern "C"修饰符。使用方法是,把该修饰符添加到调用约定必须是__cdecl的C函数前,如DriverEntry,windows驱动函数入口函数规定为_DriverEntry@8,因此用C++编译器
一些库是用C编译而成的,而在C++平台想要使用这些库,我们可以这样引入C库函数头文件
  1.  extern"C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistry)
    {
    //do something
    return STATUS_SUCCESS;
    }
    #ifdef __cplusplus
    extern"C"
    {
    #endif
    #include<NTDDK.h>
    #ifdef __cplusplus
    }
    #endif
参考链接:
 

【原创+整理】简述何为调用约定,函数导出名以及extern C的更多相关文章

  1. C/C++/动态链接库DLL中函数的调用约定与名称修饰

    参见:http://blog.twofei.com/cc/impl/calling-convension.html 调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用 ...

  2. C/C++:函数的编译方式与调用约定以及extern “C”的使用

    转自:https://www.cnblogs.com/qinfengxiaoyue/archive/2013/02/04/2891908.html 函数在C++编译方式与C编译方式下的主要不同在于:由 ...

  3. C/C++:函数的调用约定(Calling Convention)和名称修饰(Decorated Name)以及两者不匹配引起的问题

    转自:http://blog.csdn.net/zskof/article/details/3475182 注:C++有着与C不同的名称修饰,主要是为了解决重载(overload):调用约定则影响函数 ...

  4. C++调用约定和名字约定

    C++调用约定和名字约定 转自http://www.cppblog.com/mzty/archive/2007/04/20/22349.html 调用约定:__cdecl __fastcall与 __ ...

  5. DLL中调用约定和名称修饰(一)

    DLL中调用约定和名称修饰(一) 调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用而建立的一种协议.这种协议规定了该语言的函数中的参数传送方式.参数是否可变和由谁来 ...

  6. X86调用约定 calling convention

    http://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A 这里描述了在x86芯片架构上的调用约定(calling con ...

  7. 关于函数调用约定-thiscall调用约定

    函数调用约定描述了如何以正确的方式调用某些特定类型的函数.包括了函数参数在栈上的分配顺序.有哪些参数将通过寄存器传入,以及在函数返回时函数栈的回收方式等. 函数调用约定的几种类型 stdcall,cd ...

  8. C++调用约定和名字约定 thiscall

    调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数 ...

  9. VC与JavaScript交互(二) --- 调用JS函数

    这一章,我们来动手实践VC调用JS函数. 我们动手写一个HTML,其中包含这样一段JS代码: //[html] <script type="text/javascript"& ...

随机推荐

  1. Spring Boot中使用Lombok消除POJO类模板代码

    首先,要让IDE支持Lombok,这里以idea为例进行介绍. 点击项目的“File”-—>"settings"—>"Plugins",在marke ...

  2. C语言字符串和十六进制的相互转换方式

    C语言的字符串操作并不像java,Csharp那样提供直接的方法,简单粗暴.所以,在转换的时候往往费力费时,近日做项目正好用到和java程序通讯,java发送过来的数据是十六进制数字组成的字符串,解析 ...

  3. Linux学习---指针运算、修饰符(const、volatile、typedef)及、运算符(++、--、+、-)

    const:常量.只读[不能变] char *p; const char *p; [T] 字符串内容可以为“hello world”或“aaa”,但只读(不可修改) char const *p; ch ...

  4. Particle Filters

    |—粒子滤波原理 |—基础代码的建立—|—前进 |                               |—转弯 |                               |—噪音(误差 ...

  5. 20145232韩文浩《网络对抗》MSF基础应用

    MS08-067漏洞攻击 攻击机:Kali:192.168.31.132 靶机:win XP SP3(English):192.168.31.180 在VMware中设置两台虚拟机网络为NAT模式,自 ...

  6. 将表格添加到Word文档中 ,包括表格样式设置

    创建 Table 对象并设置其属性 在您将表格插入文档之前,必须创建 Table 对象并设置其属性. 要设置表格的属性,请创建TableProperties对象并为其提供值. TablePropert ...

  7. 在windows上安装VTK

    看了很多教程,花了1天半的时间装上了,记录下. 前置条件:我安装了VS2015,用来编译工程. 参考资料 官方:http://www.vtk.org/Wiki/VTK/Building 安装:http ...

  8. CSS3——animation的基础(轮播图)

    作为前端刚入门的小菜鸟,只想记录一下每天的小收获 对于animation动画 1.实现动画效果的组成: (1)通过类似Flash的关键帧来声明一个动画 (2)在animation属性中调用关键帧声明的 ...

  9. css3等待框

    第1种效果: <div class="loading"> <span></span> <span></span> < ...

  10. 剑指offer面试题24:二叉搜索树的后序遍历序列

    题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是返回true,否则返回false. 假设输入的数组任意两个数字都不相同 解题思路:二叉搜索树的特点是根节点的左子树的值小于等 ...