2.2.1 MASM系列 1.MASM编译器介绍 MASM是Microsoft公司推出的汇编编译器。它的版本从低到高经过了很多次的升级(微软的通病,升级补丁多如牛毛)。每次升级除了例行的错误修正外都增加了一些新的功能,以至于到最后高版本和低版本的语法和功能相差很多,向下兼容性也不好。低版本的MASM固然无法编译高版本的源程序,但高版本的MASM也可能无法正常编译低版本的源程序,如MASM 4.0写的源程序常常无法在MASM 6.x上编译成功。在使用MASM系列编译器时,如果不先搞清楚特定的语法和编译选项可以在哪个版本上用,编译中就会错误连篇。所以在这里有必要了解一下MASM各版本的演变过程。 表2.1列出了不同版本MASM编译器的区别。 表2.1 MASM编译器各版本的区别 版 本 简 介 MASM 4.00 这是最先广泛使用的一个MASM版本,适用于DOS下的汇编编程。它很精巧,但使用起来不是很智能化,需要用户自己一板一眼地写出所有的代码。很多教科书上讲的8086汇编语法都是针对这个版本的,对程序员来说,它只比用Debug方便一点点 MASM 5.00 MASM 5.00比4.00在速度上快了很多,并将段定义的伪指令简化为类似 .code与.data之类的定义方式,同时增加了对80386处理器指令的支持,对4.00版本的兼容性很好 MASM 5.10 对程序员来说,这个版本最大的进步是增加了对@@标号的支持。这样,程序员可以不再为标号的起名花掉很多时间。另外,MASM 5.10增加了对OS/2 1.x的支持 MASM 5.10B 1989年推出,比上一个版本更稳定、更快,它是传统的DOS汇编编译器中最完善的版本 MASM 6.00 1992年发布,有了很多的改进。编译器可以使用扩展内存,这样可以编译更大的文件,可执行文件名相应从Masm.exe改为Ml.exe。从这个版本开始可以在命令行上用*.asm同时编译多个源文件,源程序中数据结构的使用和命令行参数的语法也更像C的风格。最大的改进之一是开始支持 .if/.endif这样的高级语法,这样,使用复杂的条件分支时和用高级语言书写一样简单,可以做到几千行的代码中不定义一个标号;另外增加了invoke伪指令来简化带参数的子程序调用。这两个改进使汇编代码的风格越来越像C,可读性和可维护性提高了很多 续表 版 本 简 介 MASM 6.00A 未发售的版本 MASM 6.00B 最后一个支持OS/2的MASM版本,修正了上一版本中的一些错误 MASM 6.10 修正了一些错误,同时增加了/Sc选项,可以在产生的list文件中列出每条指令使用的时钟周期数 MASM 6.10A 1992年发布,修正了一些内存管理方面的问题 MASM 6.11 1993年11月发布,支持Windows NT,可以编写Win32程序,同时支持Pentium指令,但不支持MMX指令集 MASM 6.11C 1994年发布,增加了对Windows 95 VxD的支持 MASM 6.12 1997年8月发布,增加了.686,.686P,.MMX声明和对相应指令的支持 MASM 6.13 1997年12月发布,增加了 .K3D声明,开始支持AMD处理器的3D指令 MASM 6.14 这是一个很完善的版本,它在 .XMM中增加了对Pentium III的SIMD指令集的支持,相应地增加了OWORD(16字节)的变量类型 MASM 6.15 2000年4月发布 不同版本MASM产生的obj文件的格式也不相同,在DOS和Win16时期,Microsoft使用的obj文件格式为OMF格式(Intel Object Module Format),到了Win32时期后改用了COFF格式(Common Object File Format),原因之一是COFF格式更像最终的PE文件,在链接的时候可以做更少的处理,MASM从6.11版本开始支持COFF格式。 用Microsoft的产品编写Win32程序,不管是使用VC还是MASM,都必须使用COFF格式,因为Microsoft的32位的Link只支持将COFF格式的obj文件链接成PE文件,另外所有的导入库等支持文件的格式也全部是COFF格式的。 单独的MASM软件包不是免费的,但免费发布的Windows 98 DDK中却包括完整的MASM 6.11d版本,Win98ddk.exe文件一开始可以在Microsoft的网站上免费下载,现在已经不再提供,但读者还可以在一些第三方的站点找到这个软件包。 注意:整个Win98ddk.exe文件有18 MB之大!得到了MASM 6.11d之后,可以从Microsoft获取升级软件一直升级到最新的版本,升级包的下载地址是: ftp://ftp.microsoft.com/softlib/mslfiles 升级包的文件名和版本号相对应,如到6.14版本的升级文件是Ml614.exe,迄今为止最新的MASM 6.15版本可以从Visual C++ 6.0 Processor Pack中获取,该软件的下载地址可以在微软的网站上查找。 2.Ml.exe的用法 不同版本的MASM在使用上有很大的不同,本节所指的是可用于Win32汇编编程的MASM 6.14及以上版本,MASM编译器的命令行用法为: Ml [/选项] 汇编源文件列表 [/link链接选项] 要注意的是汇编选项要集中写在源文件名的前面,比如下面的两条命令: Ml /c /coff /Cp Test.asm Ml /c /coff Test.asm /Cp 虽然它们都可以编译Test.asm文件,但第二句的/Cp选项由于写在了汇编源文件名的后面,实际上会被忽略掉。另外,多个选项之间一定要加空格,经常有初学者将多个选项连在一起写成“/c/coff”,结果当然是会报错,因为编译器将它当做一个选项来辨认了。 Ml在Win32汇编编程中常用的选项如表2.2所示。 表2.2 Ml的常用选项 选 项 简 介 /c(常用) 仅进行编译,不自动进行链接 /coff(必用) 产生的 obj文件格式为COFF格式 /Cp(常用) 源代码区分大小写 /Fo filename 指定输出的obj文件名 /Fe filename 指定链接后输出的exe文件名 /Fl [filename] 产生 .lst列表文件 /Gc 函数调用类型用FORTRAN或PASCAL形式 /Gd 函数调用类型用C语言形式 /Gz(常用) 函数调用类型用StdCall形式 /I pathname 指定include文件的路径 /link选项 指定链接时使用的选项 /Sc 在列表文件中列出指令的时钟周期 /Zi 增加符号调试信息 与用MASM 5.0及以下的版本编写DOS程序相比,用MASM的高版本编写Win32程序有几个必须使用的选项,如/coff等。另外,用/Zi增加调试信息在源码级调试中也很有用。 3.Link的用法 用Ml.exe编译的COFF格式的obj文件可以用Link.exe链接成可执行PE文件,Microsoft的Link.exe有两个系列的版本,用于链接DOS程序的链接器为Segmented Executable Linker;可以链接Win32 PE文件的链接器为Incremental Linker,这里指的是Incremental Linker的用法。 Link的命令行使用方法为: Link [选项] [文件列表] 命令行参数中的文件列表用来列出所有需要链接到可执行文件中的模块,可以指定多个obj文件、res资源文件以及导入库文件。Link的选项很多,常用的选项如表2.3所示。 表2.3 Link的常用选项 选 项 简 介 /BASE:地址 指定程序装入内存的基地址,一般PE文件默认的装入地址是0x400000处,dll文件装入0x10000000,用此选项可以修改这个默认值 续表 选 项 简 介 /COMMENT:注释 在PE文件的文件头后面加上文本注释,想在可执行文件中加入版权字符串可以用这个办法,如果字符串中包括空格,那么要在头尾加双引号 /DEBUG 在PE文件中加入调试信息 /DEBUGTYPE:类型 加入的调试信息类型,可以是CV或COFF /DRIVER:类型 链接Windows NT的WDM驱动程序时用,类型可以是WDM或者UPONLY /DLL 生成动态链接库文件时用 /DEF:文件名 编写链接库文件时使用的def文件名,用来指定要导出的函数列表 /ENTRY:标号 指定入口标号 /IMPLIB:文件名 当链接有导出函数的文件时(如DLL)要建立的导入库名 /INCREMENTAL:ON|OFF 是否增量链接,增量链接只重写可执行文件自上次链接后改动的部分,所以可以增加链 接速度,但会增加文件长度 /LIBPATH:路径 指定库文件的目录 /MACHINE:平台名称 指定输出的可执行程序运行平台,可以是ALPHA,ARM,IX86,MIPS,MIPS16,MIPSR41XX,PPC,SH3和SH4等 /MAP:文件名 生成MAP文件 /OUT:文件名 指定输出文件名,默认的扩展名是 .exe,如果要生成其他文件名,如屏幕保护*.scr等,则在这里指定一个具体的文件名 /RELEASE 填写文件头中的校验字段 /SECTION:节区,属性 改变节区的属性,如exe文件中代码节区的属性通常是不可写的,用户也可以在这里将它设置为可写,属性可以是:E,R,W,S,D,K,L,P和X等 /STACK:尺寸 设定堆栈尺寸 /STUB:文件名 这是一个有趣的参数,Win32文件有个简单的DOS文件头,以便在DOS下执行时打出“必须在Windows下执行”一类的消息,这部分称为DOS STUB,用户可以在这里指定用一个DOS可执行文件代替它,例如,用DOS的FDISK.EXE代替,那么程序在Windows下运行的会是用户编写的代码,但在DOS下运行的就是FDISK.EXE /SUBSYSTEM:系统名 指定程序运行的操作系统,可以是NATIVE,WINDOWS,CONSOLE,WINDOWSCE和POSIX等 /VXD 编写Windows 95 VxD驱动程序时指定 由表2.3可见,Link的选项远比MASM要复杂,但并不是所有的选项都是频繁使用的,编写普通的Win32可执行文件时,必须用的选项只有/subsystem一个,其他的都可以用默认值。 一般来说,用MASM编译和链接一个Win32汇编源程序常用的命令是: Ml /c /coff xx.asm Link /subsystem:windows xx.obj yy.lib zz.res (普通PE文件) Link /subsystem:console xx.obj yy.lib zz.res (控制台文件) Link /subsystem:windows /dll /def:aa.def xx.obj yy.lib zz.res (DLL文件) 在Ml中使用/c选项表示只生成obj文件而不是直接产生exe文件,原因是链接的时候可能需要指定资源文件,所以不能让Ml直接用默认的方式链接;/coff选项是必需的,因为链接器只支持COFF格式的obj文件,其他的选项,如/Cp和/Gz虽然也是必需的,但是由于可以在asm源文件中用伪定义设置,所以一般不在命令行中指定,以免遗漏。 使用Link的时候,/subsystem选项必须被指定,一般指定为windows,当编写控制台程序的时候要改为console。写dll的时候要用/def指定列表定义文件,同时要指定/dll选项。其他的一些参数如/stub,/section和/base等只在编写特殊用途的程序时才使用。