您的位置:首页 > 编程语言 > C语言/C++

浅谈汇编语言与Visual C++的混合编程

2013-04-06 19:21 183 查看
汇编语言是面向机器的语言,它与机器密切相关,具有占用存储空间小,运行速度快,可以直接控制硬件等特点;但是汇编语言程序的编写及调试烦琐,复杂,通用性不好,移植性差,程序员需要熟悉机器的内部结构之后才能编写汇编语言程序。

用高级语言编写城西,不要求程序员熟悉计算机内部的具体构造和机器指令,可以比较方便地设计和实现算法,所以高级语言的应用领域更为广泛。但是高级语言对硬件的直接控制能力却不如汇编语言。

通常在软件的开发过程中,汇编语言与高级语言,或不同高级语言间常常需要通过彼此联系,取长补短,充分利用各种语言提供的不同技术,完成系统的设计和实现。这种组合多种程序设计语言,通过相互调用,参数传递,共享数据结构和数据信息而形成程序的过程就是混合编程。

混合编程中的关键问题是建立不同语言之间的接口,即在不同格式的两种语言间提供有效的通信方式,根据两种语言的调用约定进行某种形式说明,实现两种语言间的程序模块互相调用,变量的相互传送以及参数和返回值的正确使用。

实现汇编语言与C/C++语言的混合程序设计有两种方法:一种方法是,在C/C++语言中直接使用汇编语言语句,即嵌入式汇编,这种方法简洁直观,但功能较弱;另一种方法是,两种语言分别编写独立的程序模块,分别产生目标代码OBJ文件,然后进行连接,形成一个完整的程序,这种方法使用灵活,功能强,但需要解决好混合汇编中的关键问题:不同语言之间的接口。

含嵌入式汇编语句的C++语言程序并不是一个完整的汇编语言程序,所以C++程序只允许有限的汇编语言指令集合伪指令

嵌入式汇编语句的规定:

1.嵌入式汇编代码支持80486的全部指令系统。Visual C++ 5.0/6.0还支持MMX指令集。对于还不能支持的指令,Visual C++提供了_emit伪指令进行扩展

2.嵌入式汇编代码可以使用MASM的表达式,这个表达式是操作数和操作符的组合,产生一个数值或地址

3.嵌入式汇编代码可使用C++的下列元素:符合(包括标号,变量,函数名),常量(包括符号常量,枚举成员),宏和预处理指令,注释,类型名及结构,联合的成员

4.嵌入式汇编代码虽然可以使用C++的数据类型和数据对象,但却不可以使用MASM的伪指令和操作符定义数据。

5.虽然嵌入式汇编不支持大部分MASM伪指令,但它支持EVEN和ALIGN。这些指令将NOP指令放在汇编代码中以便对齐边界。

6.嵌入式汇编代码可以使用LENGTH,SIZE,TYPE操作符来获取C++变量的类型和大小

7.嵌入式汇编语言中可以使用C/C++或ASM的基数计数器

8.嵌入式汇编语言中不能使用象<<一类的C/C++操作符。C/C++和MASM通用的操作符比如“*”和“[]”操作符,都被认为是汇编语言的操作符

9.可以利用C/C++宏将汇编语言代码插入源程序中。

10.嵌入式汇编中的标号和C++的标号相似,它的作用范围为定义它的函数。

对于汇编语言程序来说,若采用模块连接方式,与C/C++语言混合编程除了要保证连接程序能正确连接外,还要保证汇编源程序格式符合C/C++语言的要求。为了能够正确连接,在分别编写C++语言程序和汇编语言程序时,必须遵循一些共同的约定规则。

1.采用一致的调用规范:

Visual C++语言具有三种调用规范:_cdecl,_stdcall和_fastcall.Visual C++ 默认采用_cdecl调用规范,他在名字前自动加上一个下划线,从右往左将实参压入堆栈,由调用程序进行堆栈平衡。Windows API函数采用_stdcall调用规范;它在名字前自动加一个下划线,名字后跟@和表示参数所占字节数的十进制数值,从右往左将实参压入堆栈,由被调用程序平衡堆栈。

MASM汇编语言利用“语言类型”确定调用规范和命名约定。MASM支持的语言类型有:C,SYSCALL,STDCALL,PASCAL,BASIC,FORTRAN。汇编语言与C++语言混合编程时,通常采用C语言规范:它在标识符前自动加一个下划线,按照从右到左的顺序将调用参数压入堆栈,由调用程序平衡堆栈,也可以采用STDCALL规范。C++与汇编语言混合编程的参数传递通常利用堆栈,调用规范决定利用堆栈的方法和命名约定,C++语言程序和汇编语言混合编程时要采用一致的调用规范,例如Visual C++的_cdecl,stdcall调用规范分别与MASM的C,STDCALL语言类型对应

2.命名约定

一般来说C++语言编译系统在编译C++语言源程序时,要将其中的变量名,过程名,函数名等标示符前面加下划线"_";例如,C++源程序中的变量 var,编译后变成_var。而汇编程序在汇编过程中,直接使用标识符。所以要被C++语言程序调用的汇编语言源程序中,所有标识符前都要加上下划线”_"。但是如果汇编语言程序设置了语言类型的话,就不必再标示符前加下划线,但是要保证与C++程序声明的调用规范一致

3、声明约定

对于C++语言汇编语言的共同过程名,变量名应该进行声明,并且标识符一样。C++语言对标识符区别字母的大小写,而汇编语言不区分大小写。

在C++程序中,要采用extern “C"{} 对所要调用的汇编语言程序中定义的外部过程,函数,变量予以说明,并且放在主调用程序之前,一般放在各函数体外部,一般格式为

extern ”C" int power(int,int);这些外部变量,过程,函数在C++程序中声明后,就可以再C++程序中直接使用,函数的参数在传递过程中要求参数个数,类型,顺序要一一对应。汇编语言程序的标示符(子程序名和变量名)为了能在其他模块可以,让C++语言程序能够调用它,必须用PUBLIC操作符定义它们。

汇编语言程序中使用外部标识符要利用EXTERN声明,也可以用伪指令PROTO声明子程序

4、寄存器使用约定

作为一个独立的汇编语言子程序,当然要注意寄存器的保护和恢复。对于EBP,ESP,EDI,ESI,EBX,DS,CS,SS,汇编语言子程序如果要使用它们,并且有可能改变它们的值,需要在子程序中进行保护。这些寄存器经保护后,可以利用,但退出来前必须加以恢复。寄存器EAX,EDX,AX,DX承担了传递返回值的任务

5.存储模式约定

存储模式处理程序,数据,堆栈在主存中的分配和存取,决定代码和数据的默认指针类型。存储模式在C语言中也成为编译模式或主存模式。VC提供了六种存储模式,分别是:微型模式(Tiny),小型模式(Small),紧凑模式(Compact),中型模式(Medium),大型模式(Large)和巨型模式(Huge)。它们与汇编程序相应的存储模式一一对应。为了使汇编语言程序与VC语言程序连接到一起,对于汇编语言简化段定义格式来说,两者必须具有相同的存储模式。连接前,C语言与汇编语言程序都有各自的代码段,数据段,而连接后,它们的代码段,数据段就合二为一或者彼此相关。应当说明的是,被连接的多个目标模块中,应当有一个并且只有一个起始地址。

6、人口参数和返回参数的约定

Visual C++不论何种整形类型,进行参数传递时,都扩展成32位。另外,32位Visual C++中没有近,远调用之分,所有调用都是32为的编译地址,所有的地址参数也都是32位偏移地址,在堆栈中占4个字节。

参数返回时,对于小于等于32位的数据要扩展为32为,存放在EAX寄存器中返回,4~8字节的返回值存放在EDX.EAX寄存器对中返回,更大字节数据则将它们的地址指针存放在EAX中返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: