4.3 和数据相关的操作符和伪指令
操作符和伪指令并非机器可执行的指令,相反,它们是由汇编器进行解释的。开发者可以使用一系列的MASM操作符或伪指令获取数据的地址以及大小等特征信息:
OFFSET操作符返回一个变量相对于其所在段开始的偏移。
PTR 操作符允许重载变量的默认尺寸。
TYPE操作符返回数组中每个元素的大小(以字节计算)。
LENGTHOF操作符返回数组内元素的数目。
SIZEOF操作符返回数组初始化时占用的字节数。
除此之外,LABEL伪指令还提供了对同一变量重新定义不同尺寸属性的方法。本章只是讲述MASM所支持全部操作符和伪指令的一小部分。MASM仍然支持历史遗留的伪指令LENGTH(和LENGTHOF有所不同)以及SIZE(和SIZEOF有所不同)。
4.3.1 OFFSET操作符
OFFSET操作符返回数据标号的偏移地址。偏移地址代表标号距离数据段开始的距离,单位是以字节计算的。下图解释说明了一个名为myByte的变量在数据段内的偏移:
在保护模式下,偏移是32位的;在实地址模式下,偏移是16位的。
使用OFFSET的例子
.data
bVal BYTE ?
wVal WORD ?
dVal DWORD ?
dVal2 DWORD ?
如果bVal位于00000000处,那么OFFSET操作符的返回值如注释中所示
.code
mov esi ,OFFSET bVal ;ESI = 00000000
mov esi ,OFFSET wVal ;ESI = 00000001
mov esi ,OFFSET dVal ;ESI = 00000003
mov esi ,OFFSET dVal2 ;ESI = 00000007
OFFSET操作符也可以和直接偏移操作数联合使用。
4.3.2 ALIGN伪指令
可以使用ALIGN伪指令将变量的位置按字节、字、双字或段边界对齐,格式是:
ALIGN 边界值
边界值可以是1,2,4或16,把地址直接对齐到相关倍数上:
下面是书上例子的结果:
bVal BYTE ? ;00404000
ALIGN 2
wVal WORD ? ;00404002
bVal2 BYTE ? ;00404004
ALIGN 4
dVal DWORD ? ;00404008
dVal2 DWORD ? ;0040400C
4.3.3 PTR操作符
可以使用PTR操作符来重载操作数声明的默认尺寸,这在试图以不同于变量声明时所使用的尺寸属性访问变量的时候非常有用。
例如,假设要讲双字变量myDouble的低16位送AX寄存器,由于操作数大小不匹配,编译器将不允许下面的数据传送指令:
.data
myDouble DOWRD 12345678h
.code
Mov ax ,myDouble ;错误
但是WORD PTR 操作符使得将低字(5678)送AX成为可能:
mov ax ,WORD PTR myDouble
为什么不是1234h被送到AX寄存器了呢?这与之前说得使用小尾顺序存储格式有关。下图列出了myDouble变量在内存中以三种方式显示的布局:双字、两个字(5678h,1234h)和四个字节(78h,56h,34h,12h):
CPU能够以这三种方式中的任意一种访问内存,与变量定义的方式无关。例如,如果myDouble开始于便宜0000,存储在该地址的16位值是5678h,那么还可以使用下面的语句返回地址myDouble+2处的字1234h:
Mov ax ,WORD PTR [myDouble+2] ;1234h
类似地,可以使用BYTE PTR操作符把myDouble处的一个字节放到BL:
Mov bl ,BYTE PTR myDouble ;78h
注意,PTR必须和汇编器的标准数据类型联合使用:BYTE ,SBYTE ,WORD,SWORD,
DWORD ,SDWORD ,FWORD ,QWORD或TBYTE。
将较小值送较大的目的操作数中:有时候,或许需要把内存中两个较小的值送到较大的