使用MASM03
让编程改变世界
Change the world by program
代码段
.code段是代码段,所有的指令都必须写在代码段中,在可执行文件中,代码段是放在_TEXT节区(区块)中的。 Win32环境中的数据段是不可执行的,只有代码段有可执行的属性。 对于工作在特权级3的应用程序来说,.code段是不可写的,在编写DOS汇编程序的时候,我们可以为非作歹。 如果企图在Win32汇编下做同样的事情,结果就是和上面同样 “非法操作”! 当然事物总有两面性,在Windows95下,在特权级0下运行的程序对所有的段都有读写的权利,包括代码段。 另外,在优先级3下运行的程序也不是一定不能写代码段,代码段的属性是由可执行文件PE头部中的属性位决定的。 通过编辑磁盘上的.exe文件,把代码段属性位改成可写,那么在程序中就允许修改自己的代码段。 一个典型的应用就是一些针对可执行文件的压缩软件和加壳软件,如Upx和PeCompact等。 这些软件靠把代码段进行变换来达到解压缩和解密的目的,被处理过的可执行文件在执行时需要由解压代码来将代码段解压缩。 这就需要写代码段,所以这些软件对可执行文件代码段的属性预先做修改。 为了带大家更好认识这些花花绿绿的“段”到底是什么回事,小甲鱼带大家看一张图……
程序结束和程序入口
在C语言源程序中,程序不必显式地指定程序由哪里开始执行,编译器已经约定好从main() 函数开始执行了。 而在汇编程序中,并没有一个main函数,程序员可以指定从代码段的任何一个地方开始执行,这个地方由程序最后一句的end语句来指定:
end [开始地址] 这句语句同时表示源程序结束,所有的代码必须在end语句之前。
end start 上述语句指定程序从start这个标号开始执行。当然,start标号必须在程序的代码段中有所定义。 但是,一个源程序不必非要指定入口标号,这时候可以把开始地址忽略不写,这种情况发生在编写多模块程序的单个模块的时候。 当分开写多个程序模块时,每个模块的源程序中也可以包括.data、.data、.const和.code段,结构就和上面的Win32 Hello World一样,只是其 他模块最后的end语句必须不带开始地址。 当最后把多个模块链接在一起的时候,只能有一个主模块指定入口地址,在多个模块中指定入口地址或者没有一个模块指定了入口地址,链接程序都会报错。
注释
注释是源程序中不可忽略的一部分,汇编源程序的注释以分号(;)开始,注释既可以在一行的头部,也可以在一行的中间,一行中所有在分号之后的字符全部当做注释处理,但在字符串的字义中包含的引号内的分号不当做是注释的开始。 [codesyntax lang="asm"]
;这里是注释
call _PrintChar ;这里是注释
szChar db ‘Hello, world; ’,0dh,0ah
[/codesyntax]
换行
当源程序的某一行过长,不利于阅读的时候,可以分行书写,分行的办法是在一行的最后用反斜杠()做换行符,如: [codesyntax lang="asm"]
invoke MessageBox, NULL, offset szText, offset szCaption, MB_OK
[/codesyntax] 可以写为: [codesyntax lang="asm"]
invoke MessageBox,
NULL, ;父窗口句柄
offset szText, ;消息框中的文字
offset szCaption, ;标题文字
MB_OK
[/codesyntax]
调用API函数
首先,API 是什么?
答:Win32程序是构筑在Win32 API基础上的。在Win32 API中,包括了大量的函数、结构和消息等。 它不仅为应用程序所调用,也是Windows自身的一部分,Windows自身的运行也调用这些API函数。 在DOS下,操作系统的功能是通过各种软中断来实现的,如大家都知道int 21h是DOS中断,int 13h和int 10h是BIOS中的磁盘中断和视频中断。 当应用程序要引用系统功能时,要把相应的参数放在各个寄存器中再调用相应的中断,程序控制权转到中断中去执行,完成以后会通过iret中断返回指令回到应用程序中。
DOS汇编下的Hello World程序中有下列语句: [codesyntax lang="asm"]
mov ah, 9
mov dx, offset szHello
int 21h
[/codesyntax] 解释:这3条语句调用DOS系统模块中的屏幕显示功能,功能号放在ah中,9号功能表示屏幕显示,要输出到屏幕上的内容的地址放在dx中,然后去调用int 21h,字符串就会显示到屏幕上。 这个例子说明了应用程序调用系统功能的一般过程。首先,系统提供功能模块并约定参数的定义方法,同时约定调用的方式,同时约定调用的方式,应用程序按照这个约定来调用系统功能。 在这里,ah中放功能号9,dx中放字符串地址就是约定的参数,int 21h是约定的调用方式。 下面来看看这种方法的不便这处。首先,所有的功能号定义是冷冰冰的数字,int 21h的说明文档是这样的:int 21h说明文档
再进入09号功能看使用方法: [codesyntax lang="asm"]
Print string (Func 09)
AH = 09h
DS:DX -> string terminated by “$”
[/codesyntax] 这就是DOS时代汇编程序员都有一厚本《中断大全》的原因,因为所有的功能编号包括使用的参数定义仅从字面上看,是看不出一点头绪来的。 另外,80x86系列处理器能处理的中断最多只能有256个,不同的系统服务程序使用了不同的中断号,这少得可怜的中断数量就显得太少了。 结果到最后是中断挂中断,大家抢来抢去的,把好好的一个系统搞得像接力赛跑一样。 [buy]
获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://urlxf.qq.com/?BzeuumI']视频下载[/Downlink]