64位汇编语言的编程艺术
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.6 运行第一个MASMC++的混合程序

本书通常将汇编语言模块(包含一个或多个使用汇编语言编写的函数)与调用它的C/C++主程序相结合。由于由汇编语言和C++语言组成的混合程序的编译及执行过程与独立MASM程序的略有不同,因此本节将演示如何创建、编译和运行这样一个混合程序。程序清单1-2提供了调用汇编语言模块的C++主程序。

程序清单1-2 示例C/C++程序(listing1-2.cpp文件),该程序调用了汇编语言函数

//程序清单1-2

//一个简单的C++程序,该程序调用了一个使用汇编语言编写的函数。

//需要包含stdio.h头文件,以便程序能够调用“printf”函数。

#include<stdio.h>

//extern“C”命名空间可以防止C++编译器的“名称篡改”。

extern"C"

{

//以下是使用汇编语言编写的外部函数,本程序将调用该函数:

void asmFunc(void);

};

int main(void)

{

printf("Calling asmMain:\n");

asmFunc();

printf("Returned from asmMain\n");

}

程序清单1-3是可独立运行MASM程序的改进版,其中包含asmFunc()函数,此函数被C++程序调用。

程序清单1-3 MASM程序(listing1-3.asm文件),被程序清单1-2中的C++程序调用

;程序清单1-3

;一个简单的MASM模块,包含一个空函数,被程序清单1-2中的C++代码调用。

.CODE

;(有关option伪指令的说明,请参见后续正文。)

option casemap:none

;以下是“asmFunc”函数的定义。

public asmFunc

asmFunc PROC

;空函数,直接返回到C++代码。

ret;返回到调用方

asmFunc ENDP

END

相对于原始的programShell.asm源文件,程序清单1-3包括三处修改。首先,有两个新的语句,即option语句和public语句。

option语句指示MASM将区分所有符号的大小写。这是非常必要的操作,因为在默认情况下,MASM不区分大小写,并将所有标识符映射为大写(意味着asmFunc()函数将转换为ASMFUNC())。而C++是区分大小写的程序设计语言,会将asmFunc()和ASMFUNC()视为两种不同的标识符。因此,必须指示MASM区分标识符的大小写,以免混淆C++程序的语义。

注意:MASM标识符可以以美元符号($)、下划线(_)或字母字符开头,后面跟零个或多个字母、数字字符、美元符号或下划线字符。标识符本身不能由$字符组成($符号在MASM中具有特殊意义)。

public语句声明asmFunc()标识符将对MASM源文件和目标文件的外部可见。如果没有该语句,那么只能在MASM模块内访问asmFunc(),C++编译就会报错:asmFunc()是一个未定义的标识符。

程序清单1-3和程序清单1-1之间的第三个区别是,函数名从main()更改为asmFunc()。如果在汇编代码中使用名称main(),则由于C++程序中也包含一个名称为main()的函数,因此C++编译器和链接器会出现混乱。

为了编译和运行这些源文件,可以使用如下所示的命令:

ml64命令使用了“/c”选项,该选项表示“仅编译”,并且不尝试运行链接器(如果运行链接器则将失败,因为listing1-3.asm不是一个可独立运行的程序)。MASM的输出是一个目标代码文件(listing1-3.obj),该文件作为下一个命令中Microsoft Visual C++(MSVC)编译器的输入。

cl命令在listing1-2.cpp文件上运行MSVC编译器,并将汇编代码(listing1-3.obj)进行链接。MSVC编译器的输出是一个可执行文件listing1-2.exe,从命令行执行该程序就会产生预期的输出结果。