写在前面的话:
在准备做教程的时候去查资料,关于WIN32下汇编方面的,本来想找些现成的拿到教程里用下,但发现貌似只有一篇,是2005年时jhkdiy写的,而且翻来翻去发现所有图片也都失效了。所以准备自己写一个算了,一劳永逸,还是拿jhkdiy前辈的作品为基础,大量的内容都是抄用原文的,只是把已经丢失的部分都补上,毕竟大家看那个内容应该已经习惯了。
正文:
现在很多朋友都在学习汇编语言,一方面汇编语言是大学计算机课程的必修课,另一方面则是为了从其它语言转到汇编语言来,无论什么原因,我认为学习汇编语言是件很有趣的事,学习它不但可以深入了解编程语言的内部表现,也是进一步了解操作系统的途径。可是很多朋友不知道汇编语言也可以开发基于Windows的窗口程序,现在64位CPU都已经在应用了,而在学校学的汇编还是十年前的8086/8088汇编语言,不但是基于Dos环境的16位汇编语言,而且用于开发程序的MASM也是不支持32位的。所以很多朋友的感受是在学校学了汇编等于没学,因为学到的知识在Windows平台上根本用不上或不知如何去用。
有部分朋友原来学过其它语言,如VB、Delphi、C++等等,随着学习的深入而想学习汇编语言,因为学习加解密和逆向工程汇编是必学的语言。而且如果是追求程序的高效和灵活的话汇编更是不二之选。
学习汇编语言的基础不难,难的是怎么用的问题,如何能在Windows环境下用汇编语言解决一些实际的应用问题正是很多朋友想了解的知识。这里有必要提一下Win32汇编的编程方式,所谓的Win32Asm就是利用汇编语言来直接调用Windows系统提供的API函数,其中不加任何限制和封装。而现在很多语言都或多或少地对API函数进行了封装,诸如我们熟悉的VC中的MFC就把很多API函数封装成类的成员函数,VB就封装得更厉害了。如果你已经有使用API函数的经验,如果你已经有汇编语言的基础,那么你进入Win32Asm只是换个环境而已,没有其它的路障在你面前。那么究竟如何在已有汇编基础的情况下学习Windows环境的编程呢?有这方面的文章或资料吗?可以说很少!但都是精品,Win32汇编界公认的入门经典是Iczelion的Win32汇编教程,网上同时有它的英文版和中文翻译版下载,如果找不到的话给个邮件给我。另外一个就是国内的罗云彬编著的《Windows环境下32位汇编语言程序设计》网上也有该书的pdf文件下载。可是两种教程都没有介绍在Windows环境下的汇编IDE使用,罗云彬的书依然建议用makefile方式来手工编译程序,而源代码的编辑则用editplus来做。老实说,当一个人已经熟悉了一种环境后在另一个环境下总会有所比较,而比较的结果是:用汇编开发程序还是这么麻烦,我已经习惯了VB、VC等Windows环境下的集成开发环境,一下子要自己整合编辑、编译、连接、运行、调试等的工具确实是一个不好的开端。难道就没有一个类似于Vb、VC的汇编集成开发环境吗?还是那句:很少,但都是精品!最多人使用的莫过于RadAsm了,最新版本是RadASM 2.2.0.3d (09-14-2005),整个程序很像我们熟知的VB开发界面,一样可以像VC那样用向导方式建立一个工程。关键字着色、自动完成API函数等,总之在常用开发环境下有的功能它都有,没有的它也有。它支持多种汇编编译器,目前支持MASM、TASM、NASM、FASM、GoAsm、HLA(High Level Assembly);还支持多国语言,够多了吧。另外一个受人瞩目的汇编IDE是WinAsm,最新的版本是WinAsm V5.0.4.142 ,它同样的是一个出色的汇编开发环境,老实说,我个人感觉它和Radasm并没有很大的区别,无论是开发界面和功能上都大同小异。或许造成用户群的多少只是因为个人喜好不同而造成的。遗憾的是它目前只有英文版,只支持MASM。还有一个小有名气的是Easy Code,最新的版本是Easy Code 1.00.0.0029(9-23-2005),这个开发环境好像是VB环境的近亲,因为第一次看到它的时候以为打开了Vb,实在太像了。而且它对窗口和控件做过了一定的封装,如我们知道双击在VB窗口中建立的按钮可以直接跳到该按钮的代码编辑行,而这个Easy Code也有同样的功能。
前面说的都是国外的IDE,国内有没有呢?有,我目前知道的只有AogoSoft的MASMPLUS,相信很多朋友都知道http://www.aogosoft.com/,这个国内以纯汇编讨论的编程站点汇集了很多的汇编高手,这个MasmPlus正是站长Aogo大哥写的。这个小型的masmplus颇为简洁,但确有很强大的编辑功能,由于还处于开发中,目前只有测试版,有兴趣的朋友可以到上面的主页里下载试试。
值得一提的是,上面介绍的所有开发环境都是免费的,让我们真诚地对这些无私奉献的程序英雄们说声谢谢吧。
好了,上面介绍了win32Asm的开发环境,到底怎么上手呢?我并无意将自己的嗜好强加于各位读者,但还是建议用RadAsm来入门Win32Asm的IDE,没有其它原因,只因为简单好用而且功能强大,等自己熟悉它之后再试试其它AsmIDE也不迟。令我奇怪的是下载的RadAsm并没有自带帮助文件,而要自己单独下载,以至于我一开始的时候更本无法上手,只能慢慢地摸索才知道它的很多的功能。下面我将会用RadAsm2.2.0.1来介绍RadAsm的简单使用,更多的功能就等待你去发掘了。
(1)代码编辑区,所有关键字着色,当然配色是可以改的,编辑区除了有普通文本编辑的功能外,它还有列选择和过程隐藏功能,例如过程名的最左边有一个“-”号的框,可以单击它来隐藏具体代码或显示所有文本。Ctrl+B进行列选择、Crtl+E展开所有的模块、Shift+F8下书签。
(2)API函数自动检索,例如键入了“SetWindow”后,自动列出所有以SetWindow开头的API函数。上下键进行函数选择,按下“Tab”键自动键入所选的函数。
(3)下图这一个小小框很有用,它完整地列出了API函数原型,当你的鼠标在一个函数上的时候它就显示改函数的原型。菜单“视图”->“信息工具”可以显示或隐藏该窗口。
(4)下图中这是一个输出窗口,在编译程序时它输出编译信息,如果有错的话会提示那里错了(显示行号),错了什么(错误信息),这里实质是各个编译器的输出信息,因编译器的不同而不同。菜单“视图”->“输出窗口”或 工具栏的图标可以显示或隐藏该窗口
(5)下图中从左到右3个按钮的功能为:1:显示或隐藏行号;2:展开所有模块;3:隐藏所有模块,大家都知道汇编程序通常都很长,动不动就有千行的代码,在这么长的代码中找到一个函数模块并不是一件很快的事,这时我们就可以利用2、3的功能来方便我们查看代码
(6)下图这里标出了当前打开的窗口,可以利用F6浏览下一个窗口,Alt+1。。9切换到从左数起的第N个窗口,例如图中只有2个窗口,则可以按下Alt+1切换到从左边数起的第一个窗口。
(7)下图这是工程管理窗口,每建立一个程序都有一个工程文件,将代码文件和资源文件分开管理,类似于VB的工程管理窗口。在这里可以为工程添加和删除文件或资源。
(8)下图这是工程属性窗口,如果当前在编辑代码,则它列出代码中的所有函数名,双击列表中的函数名可以直接跳到该函数的首行。如果要查看代码中有那些常数定义和结构定义可以其上的下拉列表框中选择。
(9)这四个按钮就是:编译、构建、运行、构建并运行按钮。编译按钮只编译代码文件,不编译资源文件;构建按钮则同时编译汇编文件、资源文件、和进行连接成Exe文件;运行按钮不用介绍了吧。构建并运行按钮则一次搞定所有的工作:编译代码文件、连接obj文件和Res文件、如果其中没错的话则运行程序,如果任何一项有错都会停止而提示错误信息。几个快捷键是:
Shift+F5 编译资源文件(即编译Rc文件为Res文件)
F5 编译ASM文件
Alt+Ctrl+F5 连接文件
Alt+Shift+F5 构建
Alt+F5 编译、连接、运行
Ctrl+Shift+F5 运行程序
RadAsm安装和配置
现在对RadAsm应该有一点认识了吧,下面介绍RadAsm的安装和环境的配置问题,本节的最后用一个简单的小程序来测试我们的IDE是否配置妥当。
呵呵,其实RadAsm根本不用安装,下载到的是一个压缩包,直接把它解压缩到一个文件夹中就可以了,为了讲解的方便,我以自己的配置为例:系统是Win2000-Pro,RadAsm的版本是2.2.0.1,我把RadAsm解压缩到F:\Asm\ RadASM22en\ 文件夹中;汇编编译器为Masm32V8.2, 下载后也是一个自解压文件,我把它解压到F:\Asm\masm32\ 文件夹中。如果你下载了RadAsm的语言包,则可以把它解压到RadAsm22en 文件夹中。好了,安装RadAsm就是这样简单的了,基本上没什么注意的地方。
现在讲讲RadAsm的配置,进入RadAsm22en 文件夹,运行RadAsm.exe 。如果打开后是英文界面而你又想使用中文,则可以通过菜单:选项——语言选项 选择“简体中文”,然后单击“Ok”按钮来切换到中文界面:
下面的讲解都会以中文界面为准,虽然这样做有可能会因为各中文翻译有所不同而造成中文显示不同,但相信大家都能理解其中的意思。
我们首要的任务是配置MASM32,单击菜单 选项à路径设置,在弹出的对话框中即可设置汇编编译器的路径:
最重要的是设置好masm32的路径,只要该路径设置好,整个开发环境就可以立即工作了。
可见RadAsm的安装和配置都很简单,为了验证我们配置的环境能否正常工作,下面做一个只显示一个对话框的程序来进行测试。单击菜单 文件à新建文件 或按快捷键 Ctrl+N,在代码编辑窗口中键入如下的代码:(注意大小写敏感)
完成后我把代码保存为F:\backupDoc\test.asm,然后再单击菜单 构建。
如果大家还记得的话,就知道这是编译、连接、运行一次搞定的选项,当编译器路径没有配置错误,程序即会进行编译、连接和运行。
至于汇编代码我就不解析了,也不是本教程的范围。如果编译期间发生了错误,则可以在输出窗口中查看错误提示,一般第一次的错误都是没有设置好Masm32的路径。如果没错的话RadAsm会显示整个编译和连接的过程,如上面的程序就输出如下信息:
F:\Asm\masm32\Bin\ML.EXE /c /coff /Cp /nologo /I"F:\Asm\masm32\Include" "F:\backupDoc\test.asm"
Assembling: F:\backupDoc\test.asm
F:\Asm\masm32\Bin\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 /LIBPATH:"F:\Asm\masm32\Lib" "F:\backupDoc\test.obj"
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Executing:
"F:\backupDoc\test.exe"
Make finished.
Total compile time 1693 ms
可以从上面的示例知道,用RadAsm集成开发环境一点也不比那些高级语言的IDE逊色,用RadAsm也比自己手工编辑makefile要简单的多,用它来练习Iczelion和罗云彬的教程是很不错的选择。
RadAsm开发标准窗口程序
开发窗口程序主要有两种方式,一种是创建标准的窗口程序,这过程需要先填充WNDCLASSEX结构,然后则是注册窗口——创建窗口——显示窗口——进入消息循环——对消息进行处理;另一种更为常用的是基于对话框的窗口,这种方式首先建立资源文件,资源包括对话框、各类标准控件、图标、光标、BMP文件等,如果用过Vc的朋友就一定不会陌生了,建立好资源后将资源编译成RES文件,然后在程序中使用各种资源,这种方式的好处是省去了建立标准窗口的步骤,而且对话框也是与用户进行交互的主要工具,程序员也可以集中关注程序功能而不必花太多时间在界面上。
这一节主要讲怎样利用RadAsm建立工程,编写标准的窗口程序。为了更直观地讲解RadAsm的使用,我们将建立一个基于对话框的RadAsm程序的工程。你将会看到,除了单击下一步外,剩下需要做的只是粘贴代码,按一下工具栏上的“go all”按钮来编译、连接、运行程序。一切将会简单而易行。
好了,我们现在打开RadAsm,单击菜单 文件——新建工程,在弹出的对话框中设置好工程名和工程的类型,如下图所示:
由于工程类型的选择影响到整个程序的编译和连接,所以大家在选择时不可以随便选一个类型就完事了。下面列出几个常用的工程类型:
1:如果要开发一个带有资源的标准窗口程序,则选择Win32App类型,
假如程序要用到对话框、图标、菜单、快捷键等的话就应该选择这个类型。
2:如果要开发一个没有资源的标准窗口程序,则选择Win32App(No Resource) 类型,一般不用资源的情况很少,但本节用来测试的例子就是一个没有资源的标准窗口程序。
3:如果要开发一个Windows下的控制台程序,则应选择Console APP 。
4:如果只开发一个Dll,则应选择Dll project类型。
设置好后单击“下一步”按钮;现在程序问你是否使用模板,这要看具体做什么程序了,如建立标准窗口程序可以使用“WIN32EXE.tpl”模板,对话框程序可以使用“DialogApp.tpl”模板。当然可以不使用模板,我们现在就这么做,在模板选项中单击“None”选项,然后单击“下一步”按钮。
来到这里我们可以设置需要那些类型的文件和文件夹,当然,“ASM”文件是必选的,其它有用的选项我们在讲解对话框程序时再述。再次单击“下一步”按钮,设置如上图所示。
好了,大家都可以看到工程向导到这里就完成了,单击“完成”按钮吧。
现在工程就建立完成了,是不是很容易?嗯!现在看看开发窗口右边的工程管理器窗口,我们刚才建立的工程生成了一个“Test.Asm”文件,该文件就是主代码文件了,我们可以双击它来打开代码编辑窗口:
现在把代码粘贴过来,如果格式不好自己再整理一下;考虑到有些朋友手头上暂时没有该例子的代码,没有的朋友可以直接复制下面的文本到RadAsm的代码编辑窗口中:
.const
IDD_DLG_MAIN equ 1000
IDC_EDT_OUTPUT equ 1003
IDC_EDT_FIRST equ 1001
IDC_EDT_SECOND equ 1002
IDC_BTN_OUTPUT equ 1007
IDC_BTN_EXITAPP equ 1008
.data
szExitApp db "你真的要退出程序吗?",0
szTitle db "对话框程序",0
;将两个字符串合并为一个的格式化字符串。
szFormat db "%s%s", 0
hInstance dd ? ;程序实例句柄
.code
DlgProc proc uses ebx esi edi hwnd, uMsg, wParam, lParam
;定义了三个局部数组,类型均为字节型
LOCAL @szBuffer1[256]:byte
LOCAL @szBuffer2[256]:byte
LOCAL @szOutputBuf[512]:byte
mov eax, uMsg
.if eax == WM_INITDIALOG
;这里编写窗口初始化的代码,下面是将三个局部数组清零
invoke RtlZeroMemory, addr @szBuffer1, sizeof @szBuffer1
invoke RtlZeroMemory, addr @szBuffer2, sizeof @szBuffer2
invoke RtlZeroMemory, addr @szOutputBuf, sizeof @szOutputBuf
.elseif eax == WM_COMMAND
mov eax, wParam
.if ax == IDC_EDT_FIRST
;这里编写处理第一个文本框的代码
.elseif ax == IDC_EDT_SECOND
;这里编写处理第二个文本框的代码
.elseif ax == IDC_BTN_OUTPUT
;先获取两个文本框的文本,分别保存在@szBuffer1和@szBuffer2中
;然后通过格式化函数wsprintf将两个文本合并,最后输出到第三个文本框中。
invoke GetDlgItemText, hwnd, IDC_EDT_FIRST, addr @szBuffer1, sizeof @szBuffer1
invoke GetDlgItemText, hwnd, IDC_EDT_SECOND, addr @szBuffer2, sizeof @szBuffer2
invoke wsprintf, addr @szOutputBuf, addr szFormat, addr @szBuffer1, addr @szBuffer2
invoke SetDlgItemText, hwnd, IDC_EDT_OUTPUT, addr @szOutputBuf
.elseif ax == IDC_BTN_EXITAPP
invoke SendMessage, hwnd, WM_CLOSE, 0, 0
.endif
.elseif eax == WM_CLOSE
;这里处理程序退出代码
invoke MessageBox, hwnd, addr szExitApp, addr szTitle, MB_ICONQUESTION or MB_YESNO
.if al == IDYES
invoke EndDialog, hwnd, NULL
.endif
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
DlgProc endp
;程序入口点
start:
;获取实例句柄
invoke GetModuleHandle, NULL
mov hInstance, eax
;调用对话框函数来显示对话框。
invoke DialogBoxParam, hInstance, IDD_DLG_MAIN, NULL, offset DlgProc, NULL
invoke ExitProcess, NULL
end start
现在右键单击“Test.Rc”,在弹出的菜单中选择“新建”——“对话框”菜单,如下图所示:
紧跟着会弹出一个要求保存对话框资源文件的对话框,双击“Res”文件夹,我们把对话框资源文件保存在里,在文件名中填上“Test”作为资源文件名。之后程序会自动切换到资源编辑界面,这里就是RadAsm自带的资源编辑界面了,好了,相信大家对这个环境还是比较熟眼的,下面就是添加和修改各控件的属性了,先修改对话框本身吧,设置如下的属性:
对话框属性名
设置值
Name
IDD_DLG_MAIN
Caption
对话框程序
MaxButton
False
Font
Tahoma
StartupPos
CenterScreen
其它的属性默认即可。
接着我们添加三个文本框、三个标签、两个按钮,分别设置如下属性:
文本框1属性名
设置值
Name
IDC_EDT_FIRST
AutoScroll
Horizontal
-------------------------
文本框2属性名
设置值
Name
IDC_EDT_SECOND
AutoScroll
Horizontal
-------------------------
文本框3属性名
设置值
Name
IDC_EDT_OUTPUT
AutoScroll
Both
MultiLine
True
-------------------------
标签1属性名
设置值
ID
-1
Caption
第一个字符串:
-------------------------
标签2属性名
设置值
ID
-1
Caption
第二个字符串:
-------------------------
标签3属性名
设置值
ID
-1
Caption
输出字符串:
-------------------------
按钮1属性名
设置值
Name
IDC_BTN_OUTPUT
Caption
输出(&O)
-------------------------
按钮2属性名
设置值
Name
IDC_BTN_EXITAPP
Caption
退出(&E)
整个对话框最后设计成下图所示:
如果想预览一下对话框的运行效果可以单击工具栏上的按钮来进行。整个界面设计好后别忘了保存,直接按“Ctrl+S”就可以。
好了,现在就等着你按下“Alt+F5”了,如果一切顺利的话立即可以看到程序运行,如下图所示:
程序的功能是先获取两个文本框的文本,然后通过单击“输出”按钮来一并输出到第三个文本框中。