80X86 汇编语言之地址表达式中的一些特殊算符

1、属性定义运算符

1.1、类型运算符 PTR

PTR 即 PoinTeR。

使用格式:类型 PTR 地址表达式

功能:指明紧跟其后的地址表达式的类型属性,但保持它原来的段属性和偏移地址属性不变。

根据地址表达式的不同值,类型可以是 BYTE、WORD、DWORD、FWORD、NEAR、FAR 等。

为了能将源程序中的机器指令语句正确翻译成目标代码,汇编程序要求操作数地址的类型非常明确。对大多数双操作数指令,还要求源、目的地址的类型一致,即同时为字节类型、字类型或双字类型, 否则, 在汇编时就会因为类型不明确或类型不一致而出错。为了避免这些语法错误, 就必须分清何谓类型明确, 何谓不明确(或说模糊), 怎样使模糊的类型变为明确, 怎样使类型不一致的变为一致, 下面分别进行说明。

由于寄存器明显地分为 8 位、16 位和 32 位,如果操作数在寄存器中,说明操作数的类型是相当明确的。例如:MOV AL, BL 为正确语句,因为语句中的源、目的地址类型明确且一致。用数据定义语句定义的变量,可根据所使用的伪指令 DB,DW,DD... 确定出变量的类型。因此,当采用直接寻址方式时,类型也是相当明确的。但是,语句 MOV [SI], 100 是错误语句,因为源操作数是立即操作数,没有类型,而 OPD 的类型是模糊的。它采用的寄存器间接方式只指出了数据存储单元的偏移地址,却无法指出它的类型, 汇编程序也就无法确定是将立即操作数 100 送入 SI 所指的字节单元、字单元,还是双字单元。除此以外,还有以变址、基址加变址等方式寻找操作数时,若表达式中没有变量或标号,则其地 址类型也是模糊的。

汇编程序规定:由于单操作数指令只指定一个操作数地址,它的类型必须非常明确。而对双操作数指令,如果 OPS、OPD 的类型均明确,那么它们的类型必须一致;如果一个地址类型明确,一个地址类型模糊(或没有类型),汇编程序则取明确的那一个作为源和目的两操作数地址共同的类型。

类型运算符 PTR 主要用于以下情况。

① 使语句中类型模糊的操作数地址变得明确。例如 MOV [SI], 100 可改正为

MOV WORD PTR [SI], 100

② 可用来临时改变某一操作数地址的类型,使得类型不一致的两地址变为一致。

举例:

.386
DATA  SEGMENT  USE16
NUM   DB    11H,22H,33H,44H
LEN   EQU   LEN-NUM

DATA  ENDS
...
      MOV   EAX, DWORD PTR NUM  ; 临时改变 NUM 为双字类型,(NUM) = 44332211H

说明: a. PTR 临时赋予地址表达式的新类型只能在本语句有效。 b. 不带方括号的寄存器符号不是地址表达式,因此,不能用 PTR 改变寄存器的类型,例如,以下语句为错误语句:

MOV  AL, BYTE  PTR  SI

③ PTR 运算符还可以与 EQU 或等号“=”等伪指令连用,用来将同一存储区地址用不同类型的变量或标号来表示。

1.2、定义类型运算符 THIS

运算符 THIS 与 PTR 有类似功能,即指定某个变量、标号或地址表达式类型,但在具体用法上又有区别。

使用格式:THIS 类型

功能:指定下一个能分配的存储单元(也称当前存储单元)的类型。往往与伪指令 EQU 或“=”等连用,为当前存储单元定义一个指定类型的变量与标号。

例如:

DATA    SEGMENT     USE16
B       EQU     THIS    WORD
A       DD      44332211H
BB      EQU     THIS    BYTE
        DW      0FFFFH
CC      EQU     BYTE    PTR     A   ; 这里 (CC) 应该为 11H
DATA    ENDS

在该例中,第一个语句是使用运算符 THIS 将紧跟它下面的一个双字类型变量 A 重新定义为字类型,命名为 B,而第五个语句是使用运算符 PTR 将双字类型的变量 A 重新定义为字节类型,并命名为 C。变量 B、C 与变量 A 具有相同的段属性和偏移地址属性。第三个语句是使用 THIS 将紧跟它下面的一个字存储单元重新定义为字节类型,命名为 BB。

通过此例可看出 THIS 与 PTR 用法上的区别:带 THIS 的语句一定要放在定义存储单元语句的前面且不要求该语句一定有变量名(或标号);带 PTR 的语句可放在任意位置,因此,它只能将指定名字的存储区重新定义为新类型。

另外,THIS 不能像 PTR 那样临时改变地址表达式的类型。

THIS 运算符常常用来定义远标号,这在模块化程序设计中是经常要用到的。

例如:

BEGIN   EQU    THIS    FAR     ; 定义远标号 BEGIN
        MOV    CH, BL          ; BEGIN 实际上为该语句的标号
NEXT:   MOV    AL, [SI]        ; 定义近标号 NEXT

参考:《80X86汇编程序设计》(王元珍)


80X86 汇编语言之地址表达式中的一些特殊算符
http://fanyfull.github.io/2021/06/09/80X86-汇编语言之地址表达式中的一些特殊算符/
作者
Fany Full
发布于
2021年6月9日
许可协议