按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
invoke MessageBox;NULL;offset szText;offset szCaption; MB_ICONWARNING or MB_YESNO
再编译执行看,屏幕上出现了一个不一样的消息框,如图3。3所示。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第3章 使用MASM
3。2 调用API(3)
和参数说明中的一样!消息框中出现了一个惊叹号图标,按钮也变成了“是”和“否”两个按钮!MB_ICONWARNING和MB_YESNO等参数究竟是什么意思呢,MASM中显然没有这样的预定义,让我们先来找Visual C++的头文件,在WinUser。h中可以找到下面一段:
/*
* MessageBox() Flags
*/
#define MB_OK Ox00000000L
#define MB_OKCANCEL Ox00000001L
#define MB_ABORTRETRYIGNORE Ox00000002L
#define MB_YESNOCANCEL Ox00000003L
#define MB_YESNO Ox00000004L
#define MB_RETRYCANCEL Ox00000005L
#define MB_ICONHAND Ox00000010L
#define MB_ICONQUESTION Ox00000020L
#define MB_ICONEXCLAMATION Ox00000030L
#define MB_ICONASTERISK Ox00000040L
#if(WINVER 》= Ox0400)
#define MB_USERICON Ox00000080L
#define MB_ICONWARNING MB_ICONEXCLAMATION
#define MB_ICONERROR MB_ICONHAND
#endif /* WINVER 》= 0x0400 */
#define MB_ICONINFORMATION MB_ICONASTERISK
#define MB_ICONSTOP MB_ICONHAND
……
显然,MB_YESNO就是4,MB_ICONWARNING就是30h,默认的MB_OK就是0,Win32 API的参数使用这样的定义方法显然是为了免除程序员死记数值定义的麻烦。在编写Win32汇编程序的时候,MASM32工具包中的Windows。inc也包括了所有这些参数的定义,只要在程序的开头包含这个定义文件:
include windows。inc
就可以方便地完全按照API手册来使用Win32函数。
打开masm32include目录下的Windows。inc查看一下,可以发现整个文件总共有两万六千多行,包括了几乎所有的Win32 API参数中的常量和数据结构定义。正是有了这个文件中详尽的定义,Win32ASM才得以流行起来,试想一下,哪个程序员愿意每使用一个API语句,就到函数手册中去看参数,然后到Microsoft发布的Visual C++的头文件中去找对应的数值,再应用到汇编源程序中?这样会有80%以上的时间花在做无用功上(最后还是要骂Microsoft为什么不提供汇编格式的头文件,毕竟MASM32工具包不是Microsoft出的)。
有时候由于版本的原因,当使用最新的API手册时,会发现有些参数使用的常量在Windows。inc中并没有定义,这下惨了,谁都不知道类似于MB_XXXYYY的东西代表什么数值,Microsoft的《Microsoft Programmer's Reference》手册中从来就不会把参数对应的数值写进去。遇到这种情况,只有拿出最原始的办法了,就是到最新的Visual C++或SDK的include目录中去,在C语言格式的 。h头文件中把定义找出来,然后自行增补到Windows。inc中去。如果这样也找不到定义值的话,那只好放弃使用这个API了。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第3章 使用MASM
3。3 标号、变量和数据结构(1)
当程序中要跳转到另一位置时,需要有一个标识来指示新的位置,这就是标号,通过在目的地址的前面放上一个标号,可以在指令中使用标号来代替直接使用地址。
使用变量是任何编程语言都要遇到的工作,Win32汇编也不例外,在MASM中使用变量也有需要注意的几个问题,错误地使用变量定义或用错误的方法初始化变量会带来难以定位的错误。变量是计算机内存中已命名的存储位置,在C语言中有很多种类的变量,如整数型、浮点型和字符串等,不同的变量有不同的用途和尺寸,比如说虽然长整数和单精度浮点数都是32位长,但它们的用途不同。
顾名思义,变量的值在程序运行中是需要改变的,所以它必须定义在可写的段内,如 。data和 。data?,或者在堆栈内。按照定义的位置不同,MASM中的变量也分为全局变量和局部变量两种。
在MASM中标号和变量的命名规范是相同的,它们是:
1。 可以用字母、数字、下划线及符号@、和?。
2。 第一个符号不能是数字。
3。 长度不能超过240个字符。
4。 不能使用指令名等关键字。
5。 在作用域内必须是惟一的。
3。3。1 标号
1。 标号的定义
当在程序中使用一条跳转指令的时候,可以用标号来表示跳转的目的地,编译器在编译的时候会把它替换成地址,标号既可以定义在目的指令同一行的头部,也可以在目的指令前一行单独用一行定义,标号定义的格式是:
标号名: 目的指令
标号的作用域是当前的子程序,在单个子程序中的标号不能同名,否则编译器不知该用哪个地址,但在不同的子程序中可以有相同名称的标号,这意味着不能从一个子程序中用跳转指令跳到另一个子程序中。
在低版本的MASM中,标号在整个程序中是惟一的,子程序中的标号也可以从整个程序的任何地方转入。但Win32汇编使用的高版本MASM中不允许这样,这是为了提供对局部变量和参数的支持,由于在子程序入口处有对堆栈的初始化指令,所以一个子程序不允许有多个入口,其结果就是标号的作用域变成了单个子程序范围。
2。 MASM中的@@
在DOS时代,为标号起名是个麻烦的事情,因为汇编指令用到跳转指令特别多,任何比较和测试等都要涉及跳转,所以在程序中会有很多标号,在整个程序范围内起个不重名的标号要费一番功夫,结果常常用addr1和addr2之类的标号一直延续下去,如果后来要在中间插一个标号,那么就常常出现addr1_1和loop10_5之类奇怪的标号。
实际上,很多标号只会使用一到两次,而且不一定非要起个有意义的名称,如汇编程序中下列代码结构很多:
mov cx;1234h
cmp flag;1
jz loc1
mov cx;1000h
loc1:
…
loop loc1
loc1在别的地方就再也用不到了,对于这种情况,高版本的MASM用@@标号去代替它:
mov cx;1234h
cmp flag;1
jz @F
mov cx;1000h
@@:
…
loop @B
当用@@做标号时,可以用@F和@B来引用它,@F表示本条指令后的第一个@@标号,@B表示本条指令前的第一个@@标号,程序中可以有多个@@标号,@B和@F只寻找匹配最近的一个。
不要在间隔太远的代码中使用@@标号,因为在以后的修改中@@和@B,@F中间可能会被无意中插入一个新的@@,这样一来,@B或@F就会引用到错误的地方去,源程序中@@标号和跳转指令之间的距离最好限制在编辑器能够显示的同一屏幕的范围内。
3。3。2 全局变量
1。 全局变量的定义
全局变量的作用域是整个程序,Win32汇编的全局变量定义在 。data或 。data?段内,可以同时定义变量的类型和长度,格式是:
变量名 类型 初始值1;初始值2,……
变量名 类型 重复数量 dup (初始值1;初始值2,……)
MASM中可以定义的变量类型相当多,具体如表3。2所示。
表3。2 变量的类型
名 称 表示方式 缩 写 长度(字节)
字节
byte
db
1
字
word
dw
2
双字(doubleword)
dword
dd
4
三字(farword)
fword
df
6
四字(quadword)
qword
dq
8
十字节BCD码(tenbyte)
tbyte
dt
10
有符号字节(signbyte)
sbyte
1
有符号字(signword)
sword
2
有符号双字(signdword)
sdword
4
单精度浮点数
real4
4
双精度浮点数
real8
8
10字节浮点数
real10
10
所有使用到变量类型的情况中,只有定义全局变量的时候类型才可以用缩写,现在先来看全局变量定义的几个例子:
。data
wHour dw ? ;例1
wMinute dw 10 ;例2
_hWnd dd ? ;例3
word_Buffer dw 100 dup (1;2) ;例4
szBuffer byte 1024 dup (?) ;例5
szText db 'Hello;world!' ;例6
● 例1定义了一个未初始化的word类型变量,名称为wHour。
● 例2定义了一个名为wMinute的word类型变量。
● 例3定义了一个双字类型的变量_hWnd。
● 例4定义了一组字,以0001,0002,0001,0002,…的顺序在内存中重复100遍,一共是200个字。
● 例5定义了一个1 024字节的缓冲区。
● 例6定