📄 002.txt
字号:
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.octium.net。
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.movsd.com中下载。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个步骤:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -