关于C/C++与汇编的混合编程

相信试过将WIN32汇编和C/C++混合编程大多都碰到过未知外部符号一类的链接错误

那么这个错误的原因是什么?怎么才能很好的将ASM和C/C++混合在一起呢?

这要从编译出的目标文件讲起

比如在window VC环境下,编译后每一个.c或.cpp文件都将产生一个对应的.obj文件

这个.obj文件其实就是一种流行的通用文件格式COFF,其中有文件头,代码段,调试段等各种区段,类似PE文件格式,其实PE文件格式的前身就是他了,他们的文件结构其实很大部分上是相同的

为了能将ASM和C/C++目标文件链接成功,我们需要关注.obj文件中的符号描述表,所有在源程序中定义的变量,函数的名字都会经过编译器修饰并存放在这里

我们的终极目标是把不同的.obj文件链接在一起最终得到想要的可执行程序,为了达到这个目的,链接器这一关是必须过的

假设我们在一个c/c++文件中extern了一个函数表明这是一个外部引用,需要链接器在别的.obj模块中找到实体,只有成功找到才能过链接一关

于是就简单了,我们只要保证引用的符号名一样就行了!符号名都不一样你叫链接器怎么找是吧~~

于是我们的目的就变成了确保编译器生成的外部符号名和另外一个模块中的符号名一模一样,只有这样才能“随心所欲”的链接不同模块~~

到了这里,要做的就很清楚了,我们需要了解的就是编译器如何修饰符号名

在同一个平台下影响最终生成的符号名的主要2种,一是具体的编程语言,一是调用约定

这里以windows为例:

C/C++默认调用约定都是采用_cdecl

C语言是弱类型语言

.c文件即C代码经过编译后仅仅是简单的在函数名或变量名前加下划线,即_name,而linux中因为名字问题貌似曾今也这样做过后来经过改善就改回来了,而windows中这个传统就一直遗留

而如果将调用约定改为_stdcall的话,则输出函数名前加上一个下划线前缀,后面加上一个"@"符号和其参数的字节数,例如:name(int a, int b),其修饰名为:_name@8

而C++是强类型语言,为了支持重载,命名空间等许多特性,他的名称修饰就复杂的多了

下面列出C++编译时修饰约定规则,了解就行了,基本用不到

__stdcall调用约定:
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"标识结束。
其格式为?functionname@@YG*****@Z“或"?functionname@@YG*XZ“,例如
   int Test1(char *var1,unsigned long)----?Test1@@YGHPADK@Z

   void Test2()-----“?Test2@@YGXXZ”

__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI"。
VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用.

而且C++还有_thiscall调用约定,_thiscall仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定

 

具体测试只要编译出目标文件然后16进制打开.obj文件搜索函数或变量名就可以看到修饰后的名字了

 

现在如果有一个WIN32汇编中有一个叫fun,有2个参数的函数,调用约定是_stdcall,那么为了在.cpp文件中调用他,只需要extern "C"  fun _stdcall fun(DWORD ,DWORD );就OK了,反之亦然~只要符合规则,想怎么整都行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值