WIN32汇编语言教程:第02章 准备编程环境 · 2.2 编译器和链接器(1)
选择汇编编译器是开始工作的第一步。不同的编译器用法各不相同,选择合适的编译器可以使开发工作节省很多的时间。这里简单介绍几种不同系列的编译器。常用的有Microsoft公司的MASM系列和Borland公司的TASM系列编译器,还有一些小公司推出的或者免费的汇编软件包。
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的网站上下载,下载网址从最开始的位置迄今已经移动了几次,最后一次可下载的地址是:
http://www.microsoft.com/ddk/ddk98.asp
注意:整个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中获取,下载的地址是:
http://msdn.microsoft.com/vstudio/downloads/ppack/download.asp
2. Ml.exe的用法
不同版本的MASM在使用上有很大的不同,本节所指的是可用于Win32汇编编程的MASM 6.14及以上版本,MASM编译器的命令行用法为:
Ml [/选项] 汇编源文件列表 [/link链接选项]
要注意的是汇编选项要集中写在源文件名的前面,比如下面的两条命令:
Ml /c /coff /Cp Test.asm
Ml /c /coff Tasm.asm /Cp
虽然都可以编译Tasm.asm文件,但第二句的/Cp选项由于写在了汇编源文件名的后面,实际上会被忽略掉。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和/Gz等,用/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文件默认的装入地址是Ox400000处,dll文件装入Ox10000000,用此选项可以修改这个默认值 |
/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驱动程序时指定 |
上页:第02章 准备编程环境 · 2.1 Win32可执行文件的开发过程 下页:第02章 准备编程环境 · 2.2 编译器和链接器(2)