📄 002.txt
字号:
2.1 Win32可执行文件的开发过程
在DOS下,生成一个可执行文件的步骤比较简单,用编译器将源程序编译为obj文件,再用链接器将obj文件链接成exe文件,不同语言的开发过程都差不多。
DOS可执行文件中的内容基本上是由源程序中所写的代码和数据定义转换而来的。惟一的例外是带覆盖部分的exe文件,它在基本的exe文件后附加了一些自定义的数据,可执行部分的长度由文件头偏移0002h和0004h中的长度给出,后面就是附加上去的数据。这样,即使一个带覆盖的exe文件大小远远超过640 KB,在DOS下也能运行。因为操作系统只装入真正的可执行部分,然后由程序自己去读取覆盖部分的数据。一些打包软件生成的奇大无比的自解压包就采用这种结构,可执行部分是解包代码,覆盖部分是被压缩的数据。DOS对可执行文件覆盖部分的数据格式并没有规定,它是程序员按自己的方式组织的。如果程序员愿意,也可以把这些数据单独放在另外一个文件中。
Win32可执行文件叫做PE文件。PE文件的基本结构和DOS可执行文件有很大的不同。它把程序中的不同部分分成各种节区(Section),其中可以有一个节区是放置各种资源的,如菜单、对话框、位图、光标、图标和声音等。虽然可以把资源部分理解成类似DOS可执行文件中的“覆盖”部分,但资源是Win32可执行文件的标准组成部分,而且是非常重要的组成部分。所以和DOS软件的开发过程相比,Win32软件的开发中多了一个创建资源文件的步骤。
以使用MASM32软件包为例,通过如图2.1所示的Win32汇编开发软件的流程,程序员要做的工作分创建代码和创建资源两部分。
代码部分的开发工作和DOS下写代码的步骤是一样的。程序员用文本编辑器书写汇编源代码(*.asm文件),这和C源程序类似。asm文件中也可以用include语句包含数据定义和函数声明的头文件。Win32汇编的头文件一般用inc作扩展名,如MASM32软件包附带的Windows.inc文件定义了Win32 API中很多参数和数据结构,其他的inc文件则是不同DLL中的Win32 API函数声明。最后,asm文件经汇编编译器编译成以obj为扩展名的目标文件。
资源文件中可以包括对话框、快捷键、菜单、字符串、版本信息和一些图形资源等内容。资源文件的源文件是一种类似“脚本”的文本文件。其中用不同的语法定义了不同类型的资源。资源脚本文件的扩展名一般为rc,经过资源编译器编译成资源文件*.res。资源脚本文件同样用到很多预定义值,所以软件包中一般也有资源头文件可供源文件来导入。MASM32软件包中的资源头文件是Resource.h。
在资源文件中,对话框资源只记录定义值,如对话框的大小、位置等,并非真正存储对话框最后显示在屏幕上的像素。这些大小、位置等信息最后由Windows解释后才在屏幕上被绘画成像素;菜单、字符串、快捷键等由文本构成;图形资源则真正由像素组成,它们在资源脚本中被定义为一个文件名,由资源编译器从磁盘文件导入。Windows在资源文件中支持的图形文件有bmp位图文件、cur光标文件和ico图标文件。这些图形文件可以用其他图形处理软件生成。wav声音文件也是得到支持的。
图2.1 Win32可执行文件的开发过程
编译好目标文件*.obj和资源文件*.res后,最后一步是用链接器将它们链接成可执行文件。链接的时候要用到函数库。在DOS环境下编程的时候,使用的函数库是静态库。静态库是一些已经编译好的代码模块。当用户在源程序中用到某个函数的时候,链接器从库文件中将这个函数的二进制代码取出,和obj文件合在一起生成最终的exe文件。但在Win32环境下,大部分的公用函数封装在DLL文件中,以动态链接的方式供用户程序调用。这时候库文件中只需要包含函数在DLL中的位置信息,不再需要有二进制代码部分。所以链接的时候也只是把库文件中的位置信息取出放入最后的可执行文件中。Win32中这种只包含位置信息的库文件称为导入库。
Win32汇编编程中使用不同汇编编译器的时候,汇编源程序的格式和资源脚本文件的格式可能稍微有所不同。各种头文件、库文件的文件名也有所不同。所以在开始编程之前,必须先选定一种合适的编译器。
2.2 编译器和链接器
选择汇编编译器是开始工作的第一步。不同的编译器用法各不相同,选择合适的编译器可以使开发工作节省很多的时间。这里简单介绍几种不同系列的编译器。常用的有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,用此选项可以修改这个默认值
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -