📄 002.txt
字号:
参数中也可以同时带好几个目标文件名,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.microsoft.com。
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.movsd.com
包括MASM32软件包下载、简单的Win32汇编例子和一些网站链接。
● Iczlion的Win32汇编站点——http://win32asm.cjb.net
最著名的英文Win32汇编站点,包括Iczlion书写的Win32汇编教程、大量的例子和一个讨论区。这个网站需要用代理服务器访问。
● 笔者的Win32汇编站点——http://asm.yeah.net
中文Win32汇编站点,有Iczlion汇编教程的中文版以及其他的一些教程,也包括大量例子,有一个中文的Win32汇编讨论区。
2.5.2 Intel处理器资料
Win32汇编参考资料另一个重要部分是Intel处理器的资料,这些资料大部分可以在Intel的官方网站上找到,网址是http://www.intel.com,但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.editplus.com下载使用版,使用版可以通过输入注册码成为正式版本。
● UltraEdit32——这是一个文本编辑/16进制编辑软件,有EditPlus的大部分功能外加16进制编辑功能,同样有语法高亮显示等功能,笔者认为其惟一的缺陷就是没有列选择功能,这个功能在编辑中比较有用。UltraEdit32是一个共享软件,可以从http://www.ultraedit.com下载,同样可以通过输入注册码成为正式版本。
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -