| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3630 人关注过本帖
标题:汇编新手求高人指点 找很多书弄不懂
只看楼主 加入收藏
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用wangjialong在2012-11-28 16:11:39的发言:

windows 汇编语言程序设计教程 清华出版的 戴水贵编著

还有这个书啊 没听说过 罗云彬的书不错 从基础知识到编译环境的构建都有 当然 学这个首先你得会汇编 否则学不会 而且 学的是windows编程 所以windows编程也得有点了解才行

再多说就是 目前windows程序的开发趋势不是用API 而这些所谓的win32汇编神马的都是基于API的 所以 要考虑清楚 你学的这个在实际开发中用处不大的
2012-11-28 16:14
wangjialong
Rank: 2
等 级:论坛游民
帖 子:77
专家分:95
注 册:2012-11-8
收藏
得分:0 
嗯嗯  谢谢
  可是我还是不知道怎么运行啊

新手发言,请多指教。
2012-11-28 16:14
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用wangjialong在2012-11-28 16:14:19的发言:

嗯嗯  谢谢
  可是我还是不知道怎么运行啊


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.

注意:整个Win98ddk.exe文件有18 MB之大!得到了MASM 6.11d之后,可以从Microsoft获取升级软件一直升级到最新的版本,升级包的下载地址是:

  ftp://ftp.

升级包的文件名和版本号相对应,如到6.14版本的升级文件是Ml614.exe,迄今为止最新的MASM 6.15版本可以从Visual C++ 6.0 Processor Pack中获取,下载的地址是:

http://msdn.

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驱动程序时指定
 



由表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的时候,/subsytem选项必须被指定,一般指定为windows,当编写控制台程序的时候要改为console,写dll的时候要用/def指定列表定义文件,同时要指定/dll选项。其他的一些参数如/stub,/section和/base等只在编写特殊用途的程序时才使用。

2.2.2  TASM系列

1. TASM的用法

TASM是Borland公司推出的汇编编译器,也是一种使用很广泛的编译器,和MASM相比,TASM的升级没有这么频繁。TASM早在1.0版本就有了对80386处理器指令的完全支持(MASM要到5.0版本才支持80386指令),1989年推出的1.01版本修正了1.0版的一些错误;早期的版本还有TASM 3.0和TASM 4.0,其中4.0版是TASM系列编译器编写DOS程序使用最广泛的版本。

到目前为止,TASM的最后一个版本是5.0版,这个版本支持Win32编程,并单独为Win32编程附带有一整套的32位程序:32位的编译器TASM32.EXE、链接器TLINK32.EXE和资源编译器BRC32.EXE。与这些32位程序对应的16位工具在软件包中依然存在,文件名为TASM.EXE,TLINK.EXE和BRC.EXE等。

TASM 5.0命令行的使用方法是:

TASM32 [选项] 源文件名[,[目标文件名],[列表文件名],[索引文件名]][;]

在Win32编程时TASM的常用选项如表2.4所示。

表2.4  TASM 5.0的常用选项

   
    
 
/ml,/mx,/mu
 对大小写是否敏感:ml=全部敏感,mx=全局变量大小写敏感,mu=不敏感,Win32编程中必须用ml选项
 
/m#
 允许第#次编译扫描时可以向前引用,一般使用/m2
 
/i路径
 设定include文字所在的路径
 
/l,/la
 lst文件的格式:/l为正常格式,/la为扩充格式
 
/zi,/zd,/zn
 符号调试信息的控制:/zi为全部,/zd为仅有行号,/zn为不产生调试信息
 

TASM和MASM之间的导入库和目标文件等不能通用,程序员无法用Microsoft的链接器来链接TASM产生的obj文件,反之亦然,这是因为TASM的库文件和obj文件一直是OMF格式,与Microsoft使用的COFF格式不兼容。

TASM不是免费软件,无法从Borland的网站上直接下载,但在网上随处可以找到TASM 5.0版本的下载链接,Borland网站中仅提供了5.0版本到5.0r版本的升级包,升级包的下载地址是:

http://www.

2. TLINK的用法

与TASM32.exe配合的链接器为TLINK32.exe,它的用法是:

TLINK32 选项 目标文件列表,输出文件,map文件,库文件,def文件,资源文件

指定这些文件名的时候,中间必须用逗号隔开,如果不想指定某个文件名,可以在逗号中间留空,TLINK32的常用选项如表2.5所示,注意,TASM32的选项是用斜杠开头,  TLINK32的选项却用减号开头。



表2.5  TLINK32的选项

   
    
 
-c
 链接时区分大小写
 
-B:xxxx
 指定可执行文件装入内存的基地址
 
-Txx
 输出文件类型,-Tpe表示输出PE类型的exe文件,-Tpd表示输出PE类型的dll文件
 
-ax
 文件类型,-aa表示使用Windows API,-ap表示使用兼容代码
 
-v
 在输出文件中包括调试信息
 

下面是用TASM编译和链接一个Win32汇编源程序的常用命令:

TASM32 /ml /m2 xx.asm

TLINK32 /Tpe /aa /c xx.obj,,,yy.lib,,zz.res (普通PE文件)

TLINK32 /Tpd /aa /c xx.obj,,,yy.lib,aa.def,zz.res (DLL文件)

Windows API区分大小写,所以TASM32的/ml和TLINK32的-c选项必须指定,TLINK32中的-Tpe和-aa选项也必须指定,否则链接出来的就不是Win32可执行文件了。其他的选项如调试信息等则可以根据需要选择使用。

2.2.3  其他编译器

除了MASM和TASM这两种主流的汇编编译器,汇编编程中还可以用到一些其他的编译器,这些编译器大部分是免费的,如表2.6所示。

表2.6  常用汇编编译器列表

编 译 器
    
 支持编程
 
NASM
 Netwide/National Assembler,开放源代码的免费软件,使用传统的Intel语法
 DOS,Win32,Linux
 
FASM
 支持8086-80486/Pentium/MMX/SSE/SSE2指令,16/32位代码
 DOS,Win32
 
SpAsm
 Specific Assembler,用于ReactOS/Win32的汇编编译器,有简化的语法和宏指令,自带IDE环境
 Win32
 
VisualASM
 附带IDE环境
 Win32
 
Pass32
 支持面很广的编译器,一个显著的特点是支持DOS extender,可以直接将DOS extender链接到可执行文件中
 DOS,Win32,DOS DPMI
 
GASM
 GNU Assembler,兼容NASM,可以用于DOS下的保护模式编程
 DOS
 
Nbasm
 NewBASIC++ Assembler,适合于建立小规模的汇编程序,用来学习汇编是很不错的
 DOS
 
CHASM
 Cheap Assembler,用于MS-DOS编程的共享软件
 DOS
 

值得一提的是NASM,这个编译器也支持Win32汇编,不同于MASM和TASM这两个编译器,它是免费软件并且开放源代码,如果读者对编译器的原理感兴趣的话,可以从网上下载整个NASM的软件包来看一看,NASM的官方站点网址是http://nasm.

NASM不具有MASM和TASM所拥有的一些高级语法,如将带参数的调用语句自动转化成多个push指令和一个call指令,更没有MASM所有的 .if/.endif等高级语法,这使NASM用于Win32编程相当不方便,整个感觉和用MASM 4.0差不多,几乎所有的细节都需要用户自己写。但NASM的一个显著优点部分地抵消了这个缺点,因为它支持不同的平台,如Windows,Linux和OS/2等,用它写Win32程序虽然有些麻烦,但熟悉了它的语法后可以很快在Linux的汇编中上手,所以使用NASM的程序员还是不少。
2.2 编译器和链接器
2.2.4  MASM,TASM还是NASM

既然编写Win32汇编可以使用的编译器有这么多种,那么我们究竟使用哪一种呢?单从编译器的角度来说,用MASM写汇编程序是最方便的,支持@@标号,用invoke调用子程序,支持局部变量和有 .if/.else /.endif高级语法等优点就已经是足够的理由了,更不用说有Microsoft这个强大的后盾了,这是其他的编译器所无法比拟的,但使用MASM的不方便之处是它从来就不是当做一个完整的软件包发售的,要开始用MASM写Win32程序还要费很大的周折。

不同版本的MASM软件包中都没有包含资源编译器,资源编译器是当做Windows SDK的一部分发行的,或者要从Microsoft Visual Studio软件包的Common目录中找,更有甚者,和MASM软件包一同发售的Link程序竟然不是32位的,只能用来链接DOS程序,即使是6.11以上版本中也是如此。迄今为止,MASM软件包中附带的链接程序全是Segmented Executable Linker,Incremental Linker只能在Microsoft Visual Studio软件包的Visual C++目录中找到。

其他一些有用的工具也没有包含在软件包中,如库管理工具和make工具等,所以要使用MASM进行Win32汇编编程就要对软件包进行改造:一方面舍弃MASM软件包中附带的Link程序;另一方面,需要到其他地方去找资源编译器和32位的链接器等工具软件。

对初学者来说,连Win32汇编的开发要哪几个步骤及需要用什么软件都还没有底,就更不用说从不同的工具包中寻找需要的软件了(而且必须是合适的32位版本);另外,Win32编程用到的导入库在MASM软件包中并没有包括,同样要到Visual C++中去找;最重要的障碍是:MASM软件包中没有头文件,也不可能直接使用Visual C++的头文件,所有这些头文件必须自己根据资料以及参考Visual C++的 .h文件整理出来,而Windows的数据结构和预定义的数据是出了名的多,所有这些让使用MASM编写Win32汇编程序非常难以下手。

从工具包的完整性来说,TASM和NASM相对来说要好一点,TASM软件包中包括了32位的资源编译器和链接器,也有一个32位的导入库文件,这样,用户不用添加任何其他软件就可以直接用TASM写出完整的Win32程序。但TASM软件包中也没有Windows数据结构和预定义的头文件,所有资料同样需要用户自己整理。

另一方面,和MASM相比,TASM在优化方面做得不是很好,简单举几个例子:比如TASM无法处理大量的预定义,如果用户把所有的预定义整理到Windows.inc文件中,然后在源文件中包括进来,编译的时候就会出现“Out of hash space”错误,结果每次只好把要用到的定义分拣出来写成一个小的include文件;再比如在源程序中用extrn定义API函数,不管在程序中实际有没有用到这个函数,TASM都会在最后 .exe文件的导入表中加上这个函数名,这就意味着无法用偷懒的办法把所有的API函数声明写到一个include文件中去,除非用户可以忍受可执行文件中无效的字节数比有效的多得多!还有一个缺点是:TASM在定义结构的时候,不同的结构中不能有同名的字段,而Windows的数据结构定义出奇的多,结果不同结构中的同名字段要在前面加上其他内容以示区别,这就使结构定义和参考资料在字面上不符合,使用时要不停地去看结构中的字段究竟是怎么定义的。这些小缺点使TASM在使用时程序员做的无效工作比有效工作还多。

NASM的优点就是学到的语法可以直接用在Linux的汇编中,缺点也是显而易见的,就是免费软件往往缺乏强大的后盾,开发的力度肯定不如大的软件公司,具体就表现在NASM中几乎没有一点可以帮程序员省心的高级语法,而这些恰恰是编写高可维护性程序所必须具有的特征。而且,用NASM编程同样存在用户自己整理数据结构定义和预定义的问题。

比较这些编译器,可以发现很难找到直接拿来就可以开始写Win32汇编程序的软件包,因为每个软件包中都没有关键的头文件,而用户自己整理头文件不仅使程序的可移植性大打折扣,而且工程量之大使程序员只能写很小规模的程序,所以,理想的软件包应该是这样的:

● 包含所有所需工具,如汇编编译器、资源编译器和链接器等。

● 编译器支持高级语法,使源程序便于维护。

● 包含完整的头文件,如Windows的数据结构定义和预定义等。

● 包含齐全的导入库。

● 有大量的例子和说明文档。

有这样的汇编软件包吗?有!MASM32软件包就是我们的选择。

2.2.5  我们的选择——MASM32软件包

读者可能会感到奇怪,怎么又出来一个MASM32,这是什么公司的产品呢?实际上,MASM32是不同工具软件的大集合,它的汇编编译器用的是MASM软件包中的Ml.exe,资源编译器和32位链接器用的是Microsoft Visual Studio中的Rc.exe和Link.exe,同时包含了Microsoft Visual Studio中的其他一些工具,如Lib.exe和DumpPe.exe等,所有的工具都是适合于Win32编程的版本。

同时,MASM32软件包包括了详尽的头文件和导入库文件,导入库文件取自Visual C++的导入库,规模庞大的头文件则是发布者整理的,软件包中还包括了很多的例子,涉及Win32汇编的很多方面,例子收集自世界各地Win32汇编爱好者发布的源程序。为了使工具包更实用,发布者还为它编写了一个简单的IDE环境,包括一个专用的汇编源程序编辑器和源程序模板生成器等。

MASM32软件包使汇编不再只用来编写简单的程序和少量的核心模块,它的目标完全是为了用汇编写出专业的大型程序。虽然它是一个大杂烩,但发布者做了所有汇编程序员都想做、却又在庞大的工程量前止步的工作——收集合适的工具软件,收集导入库,整理出完整的头文件,收集例子文件,写帮助文档……

让我们感谢发布者Steve Hutchesson为所有的汇编程序员所做的这一切。

迄今为止,MASM32的最高版本是MASM32V7,和早一些的MASM32V6和MASM32V5版本相比,使用的编译器等可执行文件并没有什么改变,不同的地方是在头文件中增补了一些数据结构定义和增加了不少例子程序。最新版本的MASM32软件包可以在发布者的主页http://www.中下载。MASM32是一个免费的软件包,但其中的不同部分如编译器和例子程序等可能属于不同的公司和个人,使用时需要遵从他们的版权声明。

MASM32的安装界面如图2.2所示。

安装MASM32时,在选择目标驱动器后,工具包会被安装到根目录下的MASM32目录中。读者需要知道一些重要文件的位置,这在使用时非常重要,MASM32下各目录的列表和说明如表2.7所示。


图2.2  MASM32的安装界面

表2.7  MASM32的目录说明

   
    
 
\masm32
 IDE环境、内带的文本编辑程序和模板生成程序等
 
\masm32\include
 所有的头文件,Windows.inc为数据结构和预定义值的定义文件,Resouce.h为资源文件的头文件,其他 .inc文件为对应同名DLL文件中的API函数声明文件
 
\masm32\lib
 所有的导入库文件,每个.lib文件是对应DLL文件的导入库
 
\masm32\bin
 可执行文件目录,里面包括Ml.exe,Link.exe和Rc.exe等
 
\masm32\help
 帮助文件目录
 
\masm32\m32lib
 一些常用C子程序的汇编实现源程序,如熟悉的stdin和stdout等,有一定的参考价值
 
其他目录
 主要为例子和可用可不用的小工具,例子广泛收集自网上不同作者的作品,很有参考价值
 

如果不用内带的IDE环境,不看附带的例子和帮助文件,那么有了bin,include和lib这三个目录中的内容,读者就可以进行Win32汇编编程了,其他目录中的文件仅起辅助作用。

本书的编程环境就是以MASM32软件包为基础的,事实上,现在MASM32已经是最流行的Win32汇编开发包,世界上大部分的Win32汇编程序员都用它来进行Win32软件开发。

 




2.3 创 建 资 源



2.3.1  资源编译器的使用

资源编译器用来把资源脚本文件(*.rc)编译成资源文件(*.res),MASM32软件包中使用的是Visual C++附带的Rc.exe程序,TASM软件包中使用的是BRC32.exe或BRCC32.exe,两者的用法都比较简单,它们有相同的命令行语法:

Rc或BRC32 [选项] 资源脚本文件名

Rc和BRC32在使用中没有必需的选项,不像汇编编译器一样必须使用一些关键的选项。如果编译成功,就会产生以res为扩展名的资源文件,两者生成的资源文件的格式是一样的。

资源文件编写是PE开发的标准步骤,不同的语言使用的资源编译器以及生成的 .res文件格式都是一样的,没有汇编格式的资源文件和C格式的资源文件之分,所以汇编开发包中的资源编译器实际上就是C开发包中的资源编译器。由于C语言的使用远比汇编广泛,所以资源脚本文件的语法是C格式的,如等值定义语句使用#define而不是汇编常用的equ,注释使用“//”而不是“;”,头文件习惯使用 .h扩展名而不是 .inc,参数定义有“或”操作时使用“|”操作符而不是汇编的“or”操作符等,这些在使用中必须注意,否则会引起语法错误。

两种资源编译器在使用中稍微有所区别,BRC32.exe内部可以解释Windows的一些预定义值,所以不用附带头文件,只有遇到最新的预定义时才需要头文件,而Rc并没有这个功能,所以在脚本文件中必须把头文件Resource.h包括进去。

2.3.2  所见即所得的资源编辑器

资源脚本文件中一个典型的对话框定义是这样的:

DLG_MAIN   DIALOG 0, 0, 176, 66

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

CAPTION "对话框模板"

FONT   9, "宋体"

{

DEFPUSHBUTTON "退出",IDOK,120,46,50,14

CONTROL"",-1,"Static",SS_ETCHEDHORZ|WS_CHILD|WS_VISIBLE,7,38,164,2

}

第一句定义了对话框的左上角坐标为(0,0),大小为(176,66),中间的DEFPUSHBUTTON定义了一个位置为(120,46),大小为(50,14)的按钮,看到这些定义后脑袋里要出现一个正确的对话框是很不容易的,只能在纸上打格子画出来后才能明白它的模样,所以直接用文本编辑器书写资源脚本文件有诸多不便,就像谁都不会用db语句一个个像素地定义bmp位图一样,写资源脚本同样需要像图形编辑软件一样所见即所得的工具。Borland公司的Resource Workshop和VC环境内带的资源编辑器就是这样的工具。

1. Resource Workshop资源编辑器

Resource Workshop是Borland公司出品的资源编辑器,它是当做Borland C++的一个组成部分发布的,并不是一个单独的产品,但由于它使用方便,应用一直比较广泛,于是有人将它单独分离出来做成一个软件包下载,Resource Workshop的初始版本不是双字节版,所以无法支持中文,在编辑的时候输入中文,存盘后会变成乱码,非常不便,还是有“好事者”将它修改成了双字节版供人下载,在网上搜寻下载的时候要注意版本区别。

同样是上面举例的对话框,在Resource Workshop中的编辑界面如图2.3所示,是不是形象多了?Resource Workshop不但支持资源脚本文件*.rc,同时支持资源文件*.res,读者可以用它打开*.res文件,编辑后存为*.rc文件,同时也可以直接用它编辑*.rc文件且生成*.res文件,这样就可以免去用资源编译器编译脚本文件的步骤。

奇怪的是,BRCC32.exe不需要预定义头文件的支持,而同是Borland公司的Resource Workshop却没有内置窗口风格等定义值,所以在使用中需要Resource.h头文件的支持,并且,Resource.h文件必须和 .rc文件在同一个目录中,所以用它来编辑资源脚本文件的时候要注意拷贝一份Resource.h文件,如果直接编辑资源文件*.res则不需要头文件。

Resource Workshop的缺点是版本比较老,毕竟它是随早期的Borland C++发布的,所以它不支持一些新的特征,如窗口的扩展风格等,如果在 .rc文件的定义中用到这些风格,Resource Workshop会提示不认识这些关键字,如果用它打开含扩展风格对话框的 .res文件,则会提示一个Unexpected file format错误。


图2.3  Resource Workshop的使用界面

2. 用Visual C++编辑资源

Visual C++本身是一个很大的软件包,里面集成了资源编辑功能,它也是所见即所得的编辑工具,并且支持最新的资源特征,如最新的对话框风格和一些新的控件等,同时它是双字节版本,不必担心乱码问题,Visual C++也支持编辑脚本文件*.rc和资源文件*.res,可以在两者之间互相转换。单单从功能方面考虑,用Visual C++来编辑资源是一个很好的选择。Visual C++的资源编辑界面如图2.4所示。

使用Visual C++做资源编辑器的一个显著缺点就是它的规模,资源编辑的功能是集成在IDE环境中的,要使用它就要安装整个软件包,至少需要几百MB的空间!而Resource Workshop只有几MB,MASM32软件包也只有不到10MB,为了一个资源编辑功能用去几百MB的空间似乎有点好笑。

另外,用Visual C++生成的.rc文件总是包含了很多VC自己的头文件,如果将它们去掉,下次就无法再用VC打开;如果不去掉这些多余的信息,那么用Rc.exe编译的时候就要把所有需要的头文件拷贝过来,将源程序和别人交流的时候,别人要编译这个资源脚本也必须到VC中去找到这些头文件。

但Visual C++毕竟是个功能强大的工具,建议读者还是使用Visual C++来编辑资源,存盘的时候直接存为*.res文件,这样可以省去编译资源的步骤。到最后调试完成的时候或者需要交流的时候,可以保存一份 .rc文件并将文件中VC使用的多余内容去掉,整理成Rc.exe可以编译的格式。


图2.4  Visual C++的资源编辑界面



2.4 make工具的用法



2.4.1  make工具是什么

在DOS时期编写汇编程序的时候,编译器和链接器基本上不用什么参数,命令只有区区两条:

Masm xxx.asm;

Link xxx.obj;

只要做个批处理把xxx换成%1,然后在命令行键入asm.bat xxx就万事大吉了,很是方便。Win32编程就不一样了,不管编译器还是链接器都需要加上必要的选项,文件列表也多了起来,如链接器的命令行参数中要列出obj,lib,res和def等多种文件,又多了资源编译这一步,如果用批处理实现,要加的参数太多太乱,而每次用手工一行行地键入命令的话,那对程序员来说简直就是一场灾难。当然,一种简单的解决办法就是为每个编程项目单独建立一个批处理,每次改动后,运行批处理把所有模块重新编译一次,但是当程序很庞大的时候,这将花费很长时间,那么该如何处理呢?这时候就要用到make工具来维护代码了,从网上下载Win32汇编的例子程序时,常常发现除了*.asm和*.rc文件外,例子文件包中常常还有一个makefile文件,这就是给make工具用的。

make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,同样是用类似于批处理的方式——通过调用用户指定的语句来进行编译和链接。但是,批处理会执行全部命令将全部源文件编译,包括那些不必重新编译的源文件,而make工具则可根据目标文件上一次编译的时间和所依赖的源文件的更新时间自动判断应当编译哪些源文件,对没有更新过的文件不会处理,这样就可以大大提高程序调试的效率。

举例说明,我们要写一个test.exe文件,生成最后的可执行文件有4个步骤:

1. 汇编源文件x.asm,其中用到头文件common.inc,它们经Ml.exe编译成x.obj;

2. 汇编源文件y.asm,用到头文件common.inc和y.inc,它们经Ml.exe编译成y.obj;

3. 资源脚本文件x.rc,经Rc.exe编译成x.res;

4. 最后用Link将x.obj,y.obj和x.res链接成test.exe。

可以看出,当程序调试的时候,如果修改了x.asm,也就是说x.obj的文件时间比x.asm要早,就需要重新进行步骤1和4;如果修改了y.asm或y.inc,那么需要重新执行步骤2和4;如果修改的是x.rc,则步骤3和4必须重新执行;如果修改的是common.inc,因为x.asm和y.asm都和它有关,所以步骤1、2和4都要重新执行;如果同时修改了common.inc和x.rc,那么必须重复全部步骤。在这个例子中,文件的依赖关系就是:

● test.exe依赖于x.obj,y.obj和x.res;

● x.res依赖于x.rc;

● x.obj依赖于x.asm和common.inc;

● y.obj依赖于y.asm,common.inc和y.inc。

make可以根据文件的时间正确判断文件的新旧并执行相应的步骤。但make又是如何知道文件之间的依赖关系呢?这需要用户用一个描述文件来指定。前面提到的makefile就是这个描述文件,执行make工具的时候,它会默认用makefile做描述文件名来进行相应的工作,书写描述文件有规定的语法,虽然语法不是很简单,但写好以后就省事多了。

Microsoft的make工具文件名为nmake.exe,它并不是MASM软件包的一部分,但可以在Visual C++的Bin目录下找到。Borland公司的make工具文件名是make.exe,它已经包括在TASM 5.0工具包中。两者默认的描述文件名都是makefile,描述文件的语法也大同小异,只是使用时命令行参数有些不同。

2.4.2  nmake的用法

在命令行键入nmake /? 可以显示帮助信息,nmake的语法为:

nmake [选项] [/f 描述文件名] [/x 输出信息文件名] [宏定义] [目标]

说明如下:

● /f参数——如果描述文件名不使用默认的makefile,可以用/f参数指定。

● /x参数——如果想把屏幕输出的信息存到一个文件中,可以用/x参数指定(用DOS下的管道操作符nmake > 文件名的方法无效)。

● 宏定义——可以用新的定义覆盖描述文件中的宏定义。

● 目标——指定建立描述文件中描述的某个文件,如上面的例子中默认是生成最后的test.exe文件,也可以用nmake x.res指定更新x.res文件。

nmake常用的选项如表2.8所示。

表2.8  nmake的常用选项

   
    
 
/A
 不检测文件时间,强制更新所有文件
 
/B
 文件时间相等时也要更新文件
 
/D
 make时显示文件新旧信息
 
/N
 显示make时要执行的命令,但并不真正执行
 
/P
 一个比较有用的选择,make时显示详细的信息
 

由于nmake的应用是基于文件时间的,当计算机的时钟不准确或文件拷贝到另一台计算机后文件时间有些偏差,那么可能文件的更新会不正确,这时最好用/A选项强制把所有文件更新一遍。在平时使用的时候,以makefile当做建立的描述文件名,那么仅键入不加参数的nmake命令就可以完成所有工作了。

2.4.3  描述文件的语法

make工具最主要也是最基本的功能就是通过描述文件来描述源程序之间的相互关系并自动维护编译工作,而描述文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并链接生成可执行文件,并要求定义源文件之间的依赖关系,为了更方便使用,文件中同时可以用一些宏定义。描述文件一般需要包含以下内容:

● 注释

● 宏定义

● 显式规则

● 隐含规则

在这里,首先为2.4.1节中有关test.exe的例子写出一个描述文件,再逐步介绍各部分的书写语法。为了方便使用,一般都把描述文件的文件名取为默认文件名:makefile。这个例子的makefile文件如下(注意前面括号里的是行号,不是文件的真正内容):

(001) # nmake工具的描述文件例子

(002) EXE = Test.exe   #指定输出文件

(003) OBJS =  x.obj \

(004) y.obj #需要的目标文件

(005) RES = x.res #需要的资源文件

(006)

(007) LINK_FLAG = /subsystem:windows  #链接选项

(008) ML_FLAG = /c /coff   #编译选项

(009)

(010) #定义依赖关系和执行命令

(011) $(EXE): $(OBJS) $(RES)

(012)   Link $(LINK_FLAG) /out:$(EXE) $(OBJS) $(RES)

(013) $(OBJS): Common.inc

(014) y.obj: y.inc

(015)

(016) #定义汇编编译和资源编译的默认规则

(017) .asm.obj:

(018)   ml $(ML_FLAG) $<

(019) .rc.res:

(020)   rc $<

(021)

(022) #清除临时文件

(023) clean:

(024)   del *.obj

(025)   del *.res

1. 注释和换行

makefile中的注释是以#号开头一直到行尾的字符,当nmake工具处理到这些字符的时候,它会完全忽略#号及全部注释字符。

当一行的内容过长的时候,可以用换行符来继续,makefile的换行符是\,如例子中的第三行和第四行可以合并为:

OBJS =  x.obj y.obj #需要的目标文件

在使用换行符的时候要注意在“\”后面不能再加上其他字符,包括注释和空格,否则nmake检测到“\”不在一行的最后,就不会把它当成换行符解释,就会出现错误。

2. 宏定义

makefile中允许使用简单的宏定义指代源文件及其相关编译信息,可以把宏称为变量,在整个描述文件中,只要符合下面语法的行就是宏定义:

变量名=变量内容

如上面例子文件中的2到8就是宏定义,在引用宏时只需在变量前加$符号,但是要注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号(),下面都是有效的宏引用:

$(LINK_FLAG)

$(EXE)

$A

$(A)

其中最后两个引用是完全一致的。

宏定义的使用可以使makefile的使用更灵活:首先可以使文件便于修改,比如把第8行和第18行中ml的选项部分写成宏定义,以后要改变编译选项的时候,只要直接在makefile文件头部改变宏定义就可以了,不必重新阅读整个makefile文件;其次,当不止一个地方用到同一个文件的时候,把文件名定义为宏定义可以减少错误,增加可读性,同时也可以便于修改;最大的好处是可以直接在命令行中用新的宏定义覆盖,比如在命令行中键入:

nmake ML_FLAG="/c /coff /Fl"

那么这时就会以新的/c /coff /Fl定义代替makefile中定义的/c /coff,在这种使用中要注意两个问题,一是宏名称要区分大小写,ML_FLAG和ml_flag是不一样的;二是定义值中有空格的时候要用双引号引起来,没有空格时可以不用双引号,如ML_FLAG=/c,这使临时使用不同的参数编译文件时可以不必修改makefile。

 
 


3. 显式规则

makefile中包含有一些规则,这些规则定义了文件之间的依赖关系和产生命令,一个规则的格式是这样的:

目标文件:依赖文件;命令   (方法1)



目标文件:依赖文件 (方法2)

  命令

在规则定义和命令行中,不能包含注释,例子中的第11和12行把宏定义展开后就是:

test.exe:x.obj y.obj x.res

  Link /subsystem:windows /out:test.exe x.obj y.obj x.res

这里的目标文件就是test.exe,它依赖于3个文件x.obj,y.obj和x.res,如果有必要,产生目标文件的命令就是下面的Link命令,整个规则可以用两种方法,用第二种方法的时候,命令可以从第二行开始,第一行的“;”省略,但是这时命令前面必须有一个Tab字符,否则nmake无法区分这究竟是命令还是别的定义。目标文件可以有多个,依赖文件也可以有多个,同时命令也可以由多个命令行组成,当然这时候就必须用第二种方法定义了。

我们也可以用test.exe生成的规则定义其他文件,如x.obj或x.res的生成方法,但nmake如何知道哪个是最终要make的文件呢?实际上nmake默认将整个描述文件的第一条规则中的目标文件认为是最终文件,如果我们把11,12行放到第13行后面,那么x.obj和y.obj的建立规则就成了第一条规则,nmake建立了x.obj和x.obj之后就不理会test.exe的建立了,所以我们必须把最终需要生成的文件放在第一条规则定义。当然,在nmake的命令行参数中可以指定要make的目标,如我们要生成x.res文件,那么不必修改makefile将x.res的描述规则移动到最前面,而是直接在命令行键入以下命令即可:

nmake x.res

参数中也可以同时带好几个目标文件名,nmake会一一处理,如果指定的目标文件没有对应的规则,nmake会返回一个出错信息:

fatal error U1073: don~t know how to make ~xxx文件~

当用户要求nmake去建造一个目标时,make会去找到这个目标的依赖规则,这时第二行中的命令并不会立刻就执行,而是首先要做一些事情:nmake先去检查依赖文件是否是另一条规则的目标文件,如果是则先处理这一条规则,否则不是,nmake再检查各个依赖文件的时间,看这些文件有没有比目标文件更新的,如果没有,nmake会决定不再重新建造目标文件,并给出提示:~xxx文件~ is up-to-date,如果依赖文件有比目标文件更新的,才执行命令。

所以一个顺序下来,所有的目标文件以及它们的依赖文件,以及依赖文件的依赖文件都会被检查并更新,总而言之,一个目标文件的建立包含了顺序正确的指令链接,这个链接结构是树状的,目标文件是根,一级级扩展到多个文件,我们要求的是nmake去建立链接中处于根部的那个文件,nmake会根据链接结构从目标开始向初始状态前进,最后慢慢回来,在这个过程中执行建立每个文件所必须的命令,一直到最终目标建立完成。

目标也可以没有依赖文件,而且目标也可以不是一个真正存在的文件,如例子第23行到第25行中的clean是一个目标,但我们并不是要生成一个clean文件,而是希望在文件调试完毕后用nmake来清除临时文件,当我们键入nmake clean的时候,工作目录下并没有clean这个文件,那么nmake就会去执行clean定义中的命令,因为nmake把每一个不存在的目标当做是一个过时的目标,如此一来,就会删除中间过程中的文件*.obj和*.res。

指出了目标文件全名的规则称为显式规则,但有些类别的文件的编译方法可以是雷同 的,如从asm文件产生obj文件的命令总是用ml,从rc文件产生res文件的命令总是用rc,对于每个文件都写一条规则有些多余,这时候就要用到隐含规则。

4. 隐含规则

隐含规则可以为某一类的文件指出建立的命令,它具体定义了如何将带一个特定扩展名的文件转换成具有另一种扩展名的文件,定义的格式是:

.源扩展名.目标扩展名:;命令   (方法1)



.源扩展名.目标扩展名: (方法2)

  命令

隐含规则的语法和显式规则相似,也是用“:”隔开,在“;”下面书写命令,也可以不用“;”而将命令写在第二行,同理,这时命令之前要加一个Tab字符。

隐含规则不能有依赖文件,所以“:”下面没有内容,例子中的第17、18行定义了从asm文件建立obj文件的隐含规则,第19和20行定义了从rc文件建立res文件的隐含规则,隐含规则中无法指定确定的输入文件名,因为输入文件名是泛指的有相同扩展名的一整类文 件,这时候就要用到几个特殊的内定宏来指定文件名,这些宏是$@,$*,$?和$<,它们的含义如下:

● $@ —— 全路径的目标文件。

● $* —— 除去扩展名的全路径的目标文件。

● $? —— 所有源文件名。

● $< —— 源文件名(只能用在隐含规则中)。

所以第19、20行中的rc $< 用于x.rc的时候就是rc x.rc。

读者可以注意到一些显式规则没有命令行,如第13行的“$(OBJS): Common.inc”指出了所有的obj文件全部依赖于Common.inc文件,第14行的“y.obj: y.inc”则指出了y.obj同时也依赖于y.inc和第13行的规则合并,y.obj依赖于Common.inc也依赖于y.inc,但是这两条规则都没有指出产生这些obj文件的命令,所以nmake处理的时候会到隐含规则中去找命令行,最后会用第18行的“ml $(ML_FLAG) $<”命令去产生这些obj文件。

 




2.5 获 取 资 料


对于程序员来说,“高手”和“菜鸟”之间的区别实际上只有两个因素:一是从事编程时间的长短不同,使经验的多少有所区别;第二个因素就是手头掌握资料的多少了,因为很多问题并不是靠自己钻研可以解决的,必须靠资料,试想在写DOS汇编程序时如果没有中断手册,可以自己钻研出来吗?实际上,大部分“菜鸟”向“高手”问的问题完全可以由参考资料解决,即使一个“菜鸟”对某个问题暂时不懂,但手头有解决问题的详细资料,经过一段时间的钻研,问题自然会解决。“高手”就是这样慢慢练成的。

在Win32汇编编程中,资料显得尤其重要。在DOS时代,整个操作系统的大小不过几十KB,所有的BASIC和C命令基本上都可以直接用人脑记忆下来,用于汇编编程的中断手册也基本上可以让人记住常用的部分。

不过,当时钟走到21世纪的时候,软件规模飞速膨胀,仅是开发工具就动辄几十MB,更不用说复杂的操作系统及其他软件了,所以现在完成一件最基本的事情都必须从文档中寻找合适的方法,大部分程序员手边的文档比字典还要厚几倍,并且,在这些浩如烟海的文档中苦苦寻找之后,还不一定能找出一个满意的解答。像Windows就是一个数据结构的迷宫,其API的资料远比DOS下的中断资料要多,在这种情况下,程序员的经验可以在程序的优化和调试方面发挥作用,但如果没有资料,连程序都写不出来,就谈不到优化和调试了。

在硬件方面,处理器的发展也很快,图书市场上的资料往往要慢一个节拍,国内的图书尤其如此,想了解最新的指令集就必须到厂家的网站上下载最新资料。所以程序员需要一个强大的信息网络来方便信息的查找,方便与软件开发商的交流,特别是通过Internet。

目前,各大软件开发商都具有各自的程序员信息网络,这些网络能为程序员提供特别的服务和帮助。所以要寻找编程资料,首选方案就是常接触这些网络,如Borland公司的Borland Community,Oracle公司的Oracle Technical Network,Sun公司的Sun Developer以及IBM公司的developerWorks等。

2.5.1  Windows资料的来源

要获取Windows的资料自然要到它的老窝——Microsoft的站点上去,Microsoft的程序员网络是MSDN(Microsoft Developers Network),在这里可以获得微软所有产品和操作系统的相关信息。它的网址是http://msdn.

MSDN是一个内容非常全面的信息网络。现在这个网络一共有300万注册用户,它不仅在互联网上建立了网站,并且也发行MSDN杂志以及可供订阅的CD和DVD,其中包括编程信息、技术论文、操作系统、文档、工具、程序代码以及新产品的Beta测试包。MSDN的技术支持方式既有免费信息服务,也有收费的服务,例如,订阅MSDN的印刷品以及购买MSDN的CD和DVD等,购买MSDN实际上等于购买了一种服务。

MSDN的收费服务是以订阅形式出现的一年4期的光盘资料库,它有3个版本:

● MSDN开发库:有知识库和一些例子代码,一般是20张左右的光盘,可以联机检索,一般可以从这里找到全部的API资料、大量的基础知识和代码。

● MSDN专业版:包括MSDN开发库的全部内容,再加上Microsoft操作系统类软件,SDK(Software Development Kit)和DDK(Device Driver Development Kit)。SDK和DDK是软件开发包和驱动程序开发包,它们包括开发软件或驱动程序的头文件、例子以及一些开发工具,要想知道一个课题的最佳解决方案就是去看对应的SDK和DDK中的例子文件。

● MSDN宇宙版:包括MSDN专业版的内容,还包括Microsoft所有软件,如Windows 2000,Office和SQL Server等,用户从一个软件Beta版时就可以开始评估使用,使开发人员可以最早拿到最新的技术与资料,但这些产品不能用于企业环境去架构网络。

MSDN的订阅费用不菲,3个版本每年的订阅费用分别为1 500元、8 200元和29 000元,这显然是一笔不小的费用,所以很多程序员还是选择在Microsoft的站点上使用联机版本,但MSDN站点在内容上显得稍微过繁,有人对此的评论是:“Microsoft每次都会提供大量的资料,以至于可能需要费些力气才能找到所需的东西,不过这总比什么都不提供强”。

从网上也可以找到MSDN的各种独立部分分别下载,如各种版本的SDK和DDK等,当然这不会在Microsoft自己的站点上。同时从网上也可以找到一些单独分离出来的帮助文件,如《Microsoft Win32 Programmer~s Reference》,《Win32 Multimedia Programmer~s Reference》,《OpenGL Programmer~s Reference》,《Windows Sockets2 Application Program Interface》以及其他几乎所有的程序员手册,它们中间包括了对应的API函数的详细资料。

使用这些Windows资料时要注意它们几乎全部是以C语言的语法提供的,因为在Win32的环境下,不管是什么语言,全部都是建立在Win32 API的基础上的,而Windows本身就是用C开发的。我们要写Win32汇编程序,参考资料也只好使用这些C的版本,这就要求读者对C语言中函数的定义、数据类型和数据结构的定义等有基础的了解。也正因如此,如果读者有用MFC编写Windows程序的经验,看完了这本书以后一定会说:“汇编,C,Windows,怎么是同一回事?”的确,在Win32环境下,所有的语言实际上是一回事,只不过Visual FoxPro,Visual BASIC等软件对API以及Windows的消息体系封装很深,Visual C++和C++ Builder等软件相对少一点,而汇编不加任何封装。

有了足够的参考资料以后,并不代表着就可以用汇编编写出常用的Win32程序了,因为毕竟这些只是金字塔的一个底边而已,爬上去的路就是学习的过程,中间最好的参考就是Win32汇编的教程和例子,Internet上有很多的站点是关于Win32汇编编程的,这里列出几个站点,读者可以从这些站点的链接中找到其他很多的相关站点:

● MASM32软件包的官方站点——http://www.

包括MASM32软件包下载、简单的Win32汇编例子和一些网站链接。

● Iczlion的Win32汇编站点——http://win32asm.

最著名的英文Win32汇编站点,包括Iczlion书写的Win32汇编教程、大量的例子和一个讨论区。这个网站需要用代理服务器访问。

● 笔者的Win32汇编站点——http://asm.

中文Win32汇编站点,有Iczlion汇编教程的中文版以及其他的一些教程,也包括大量例子,有一个中文的Win32汇编讨论区。

 

2.5.2  Intel处理器资料

Win32汇编参考资料另一个重要部分是Intel处理器的资料,这些资料大部分可以在Intel的官方网站上找到,网址是http://www.,但Intel的网站存在和Microsoft的网站同样的问题,就是资料“太多”了反而不容易查找。

Intel发布的资料大部分是以PDF格式出现的,每一类文件有惟一的编号,可以用编号或资料名称从网站的搜索栏中找到对应的PDF文件,和Win32汇编编程密切相关的是处理器结构和指令集的参考资料—Intel处理器软件开发员手册《Intel Architecture Software Developer~s Manual》,它由3个部分组成:

● 第一部分:基本体系(BASIC Architecture),编号24547004;

● 第二部分:指令集参考(Instruction Set Reference),编号24547104;

● 第三部分:编程指南(System Programming Guide),编号24547204。

编号中的前缀245470、245471和245472是文件编号,后面的04表示修订版本是第4次,读者可以在Intel的网站中输入文件编号找到这几个文件并下载使用。它们包括了最新的MMX和SSE指令的用法。

 




2.6 构建编程环境


由于Win32汇编可以采用多种编译软件,它们的环境设置方法各不相同,对已经入门的读者来说,这不是问题,但初学者往往不能很好地掌握设置的方法,以至于拿到例子程序后编译不出来,不少人往往在例子一而再、再而三编译不出来后深受打击,还没有来得及看到汇编的一点影子就“告别”了这个神秘又精彩的世界。

本书的例子是基于MASM32软件包的,本节介绍MASM32使用中的一些问题。

2.6.1  IDE还是命令行

IDE(Integrated Develope Environment)即集成开发环境,Microsoft的Visual Studio中的VC和VB等开发环境就是IDE的最好例子,MASM32软件包中同样有一个简单的IDE环境Qeditor.exe,但MASM32中编译、链接用的是Ml.exe和Link.exe,所以这个IDE环境实际上只是一个简单的文本编辑器加上一个用户可以自行设置菜单的Shell,编译链接工作靠调用其他软件完成。

如果要使用这个IDE环境,最大的代价就是不得不使用这个简单的编辑器,而一个好的文本编辑器对工作效率的影响是很大的,一个完善的文本编辑器必须包括语法高亮显示、强大的查找替换、无限次Undo和Redo操作、支持特大型的源文件等功能,MASM32中简单的Qeditor.exe符合不了这些要求。

所以建议读者还是抛弃这个IDE环境,用一个功能强大的文本编辑软件来写源程序,然后在命令行环境中用nmake来维护代码,这样有一个额外的好处,就是makefile文件同时记录了文件的编译与链接参数,可以在以后方便维护。

这里介绍两个很适合用来编辑汇编源文件的文本编辑软件:

● EditPlus——这是一个为程序员编写的文本编辑软件,内置HTML,CSS,PHP,ASP,Perl,C/C++,Java,JavaScript和VBScript的语法高亮显示,也可以下载ASM语法文件,它包括了所有文本编辑软件应该具有的功能:自定义工具菜单,显示行号,语法自动完成,列选择功能(以前只在WPS中看到过),无限次Undo/Redo和语法检查等功能。读者可以从http://www.下载使用版,使用版可以通过输入注册码成为正式版本。

● UltraEdit32——这是一个文本编辑/16进制编辑软件,有EditPlus的大部分功能外加16进制编辑功能,同样有语法高亮显示等功能,笔者认为其惟一的缺陷就是没有列选择功能,这个功能在编辑中比较有用。UltraEdit32是一个共享软件,可以从http://www.下载,同样可以通过输入注册码成为正式版本。

2.6.2  本书推荐的工作环境

本书建议读者放弃MASM32简单的IDE环境,改为在命令行下用nmake工具进行代码维护,为了建立这个环境,需要做下面的工作。

第1步:安装常用软件,包括编辑软件Editplus,MSDN,16进制编辑器hexedit,可视化资源编辑器Resource Workshop,调试工具Soft-ICE和反汇编软件W32DASM等,如果空间允许的话,最好安装Visual C++,以便使用它集成的资源编辑器。

第2步:选择一个驱动器安装MASM32软件包,安装好的目录是x:\Masm32目录,对读者来说整个软件包中重要的只有3个目录:bin目录中有汇编编译器ml.exe,资源编译器rc.exe和链接器Link.exe等执行文件;include目录中有各种头文件;lib目录中有全部导入库。MASM32没有选择地把安装目录名定为masm32,如果不满意的话,完全可以把这3个关键目录拷贝到别的用户自己命名的目录中,对使用没有任何影响。

第3步:建立源文件目录,由于Win32汇编不再像DOS汇编一样一个项目只有一个asm文件,而是包括asm,rc,makefile和图标等多个文件,如果把多个项目的文件混在同一个目录中将无法分辨,所以必须为每个项目单独建立一个目录,建议把这些目录集中在一个专门放置源程序的目录中,如x:\Source目录。

第4步:由于MASM32软件包中没有nmake.exe文件,所以要单独寻找nmake.exe并拷贝到bin目录中。

第5步:为这个环境建立一个设置环境变量的批处理文件,假设文件名为Var.bat,那么这个文件内容如下:

@echo off

set include=x:\masm32\Include

set lib=x:\masm32\lib

set path=x:\masm32\bin;%path%

echo on

文件中设置了3个环境变量:

● include变量指定头文件的搜索目录。在asm和rc文件中可以根据这个变量寻找include语句指定的文件名,避免了使用头文件的全路径名,这样以后移动了MASM32的安装位置就不必修改每个源文件中的include语句。如果使用Visual C++的集成环境来建立rc文件的话,为了使rc.exe能找到头文件,还要把VC++安装目录下的Include和MFC\Include目录包含进来,中间用“;”隔开:

set include=x:\masm32\Include;VC目录\Include;VC目录\MFC\Include

VC++安装目录一般为C:\Program Files\Microsoft Visual Studio\VC98\。

● lib变量指定导入库文件的搜索目录。在asm文件中可以根据这个变量寻找includelib语句指定的导入库文件,Link.exe也根据这个变量寻找库文件的位置。

● path变量就不必多解释了。它只是使我们不必在键入命令时带长长的路径而已。

2.6.3  尝试编译第一个程序

按照上面的步骤安装完成后,下面来编译一个程序测试一下。打开一个文件浏览窗口,切换到源文件目录x:\Source,然后把本书所带光盘中的Chapter02\Test目录拷贝过来,现在有了一个需要编译的Test.asm文件在x:\Source\Test目录中。

打开一个MS-DOS窗口,并键入Var执行已建立的Var.bat,这时环境变量和路径已经设置好了,可以键入SET命令验证一下include和path等环境串是否正确,然后键入x:以及cd \Source\Test切换到要工作的目录中,并键入nmake,当屏幕上出现如下所示的正确的编译链接信息后,Test.exe就建立完成了。

Microsoft (R) Program Maintenance Utility Version 6.00.8168.0

Copyright (C) Microsoft Corp 1988-1998. All rights reserved.

 

  ml /c /coff Test.asm

Microsoft (R) Macro Assembler Version 6.14.8444

Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 

 Assembling: Test.asm

  rc Test.rc

  Link /subsystem:windows Test.obj Test.res

Microsoft (R) Incremental Linker Version 5.12.8078

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

执行一下Test.exe,会出现一个简单的对话框,表示一个可以执行的Win32程序正确生成了。万事大吉,这样就可以开始Win32汇编之旅了!

如果编译的过程中出现“can not open file xxx.inc”或“can not open file xxx.lib”的提示时,就要检查Var.bat文件中include或lib的路径是否正确。

下面的工作就是:编辑源程序→切换到MS-DOS窗口→键入nmake编译→运行生成的可执行文件→切换到文本编辑器修改源程序……如此循环往复调试程序。

执行Var.bat设置环境变量的操作只需在每次刚打开MS-DOS窗口的时候执行一次就可以了。调试Win32汇编程序时常见的桌面如图2.5所示。

屏幕上一般有个MS-DOS窗口来执行编译命令,有一个文本编辑器窗口修改源代码,同时使用MSDN等联机帮助文件,当然再开一个WinAmp窗口同时听一听MP3也不错!


图2.5  工作环境

最后提醒读者,测试本书所带光盘中的代码时,将光盘上的代码拷贝到硬盘上后,别忘了把拷贝过来的文件去掉“只读”属性,否则修改或编译时可能会因无法写文件而产生错误。

罗云彬书上的原话
2012-11-28 16:15
wangjialong
Rank: 2
等 级:论坛游民
帖 子:77
专家分:95
注 册:2012-11-8
收藏
得分:0 
那做智能车需要学哪种汇编语言?  dos吗?

新手发言,请多指教。
2012-11-28 16:16
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用wangjialong在2012-11-28 16:16:42的发言:

那做智能车需要学哪种汇编语言?  dos吗?

单片机或者类似arm的汇编罢

现在这些单片机神马的开发都可以用C语言了 你确定你一定要学汇编么 就算是学汇编 windows的汇编肯定对你特别大的帮助 难道你的智能车是运行windows操作系统的?
2012-11-28 16:18
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
貌似c和汇编都可以吧
没坐过那个东东 不清楚

DO IT YOURSELF !
2012-11-28 16:18
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用wangjialong在2012-11-28 15:48:27的发言:

我是一个汇编新手,最近装了MASM5.0和MASM32Editor但我不知道怎么运行编好的汇编程序,在网上查了好多,按他们的步骤总是进行不了一步就出现不是内部文件或外部文件的话,我的电脑系统是win7 64位的,请知道的高手帮帮我啊,我很想学好汇编

推荐一个汇编IDE

MASMPlus 百度一下就有
2012-11-28 16:18
wangjialong
Rank: 2
等 级:论坛游民
帖 子:77
专家分:95
注 册:2012-11-8
收藏
得分:0 
不是
  但我觉得学会的话对我理解智能车有帮助
    谢谢了   

新手发言,请多指教。
2012-11-28 16:19
wangjialong
Rank: 2
等 级:论坛游民
帖 子:77
专家分:95
注 册:2012-11-8
收藏
得分:0 
嗯嗯
  谢谢了
 

新手发言,请多指教。
2012-11-28 16:20
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
win32汇编 只是对开发windows程序 逆向 破解 病毒 等有一定的帮助 其他的 我只能说 呵呵 了 汇编没那么神 windows的编程更没那么神
2012-11-28 16:21
快速回复:汇编新手求高人指点 找很多书弄不懂
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017410 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved