目录
伪指令
指示性语句中的伪操作命令,无论表示形式或其在语句中所处的位置都与 CPU 指令相似,因此也称为伪指令,但两者之间有着重要的区别。
首先,CPU 指令在程序运行时由 CPU 执行,每条指令对应 CPU 的一种特定的操作,如数据传送、算术运算等;而伪指令在汇编过程中由汇编程序执行,如定义数据、分配存储区、定义段以及定义过程等。其次,汇编以后,每条 CPU 指令都被汇编并产生一条与之对应的目标代码,而伪指令则不产生与之对应的目标代码。
一、数据定义伪指令
格式:{变量名} 伪指令 操作数1 {,操作数 ...}
加花括号的是可选项,可以有,也可以没有。
常用的数据定义伪指令有以下 5 种:
- DB:定义变量为字节类型
- DW:定义变量为字类型
- DD:定义变量为双字类型
- DQ:定义变量为四字类型
- DT:定义变量为十字节类型
请看清楚是 “字” 还是 “字节” 。
1. 操作数
操作数的值不能超过伪指令所定义的范围。
① 数值表达式
DATA1 DB 32H, 30H
DATA2 DW 1000H, 100 * 6 + 88
② ?表达式:表示可以预置任意内容
DATA3 DB ?, ?, ?
③ 字符串表达式
STRING1 DB 'ABCDEF' ; 41H,42H,...
STRING2 DW 'AB', 'CD' ; 4142H,4344H,...
STRING3 DW 'ABCD' ; 错误。DW、DD不允许两个以上字节
STRING4 DD 'ABCD' ; 错误。DW、DD不允许两个以上字节
(易错)使用 DW 和 DD 伪指令时,不能用由两个以上字符构成的字符串赋初值,否则报错。若想一次性得到含有两个以上字符的字符串,则必须使用 DB 字节方式进行定义。
应用举例:
STRING1 DB 'ABCDEF' ; 41H,42H,...
STRING2 DW 'AB', 'CD', 'EF' ; 4142H,4344H,4546H
STRING3 DD 'AB', 'CD' ; 00004142H,00004344H
...
MOV AL, BYTE PTR STRING3 ; (AL)=42H
MOV AL, BYTE PTR STRING3[1] ; (AL)=41H
2. 重复操作数
功能:当同样的操作数重复多次时,可用 DUP 表示。
格式:变量名 伪指令 表达式1 DUP (表达式2)
- 表达式 1 为重复次数
- 表达式 2 为重复内容
DATA_A DB 10H DUP(?) ; 重复10H次
DATA_B DB 20H DUP(30H, 31H) ; 重复20H次30H,31H,30H,31H,...
DATA_C DW 20H DUP(3000H, 3100H) ; 重复20H次3000H,3100H,3000H,3100H,...
注意重复次数是用十进制写的还是用十六进制写的。
3. 变量的使用
变量名的含义:
- 该变量存放的是一个存储器操作数
- 该变量的段地址、偏移地址、类型
① 在指令性语句中引用
若直接引用变量名,则表示该操作数为存储器操作数,其表现形式为:段地址:[ 偏移地址 ] 。
[ ] 既指明该操作数为存储器操作数又有加号的作用。
DATA1 DB 0FEH
DATA2 DW 52ACH, 1234H
...
MOV AL, DATA1 ; (AL)=FEH
MOV BX, DATA2 ; (BX)=52ACH
MOV BX, DATA2 + 1 ; (BX)=3452H
Q:DATA2 + 1 对应的操作是什么?
A:汇编后,表达式必须要有一个确定的值。这个值可能是数值,也可能是段地址和偏移地址。对于 DATA2,汇编时只会写入它的段地址和偏移地址。这两个地址是汇编程序知道的,因为地址本来就是在汇编中分配的。但是汇编程序不知道这两个地址对应的存储单元存储的内容,因为内容要在执行后才能确定。因此,DATA2 + 1 代表偏移地址 + 1,而不是对应内容 + 1 。
当变量名出现在寄存器间接寻址的操作数中时,它表示该变量的偏移地址。
DATA3 DB 10H DUP(?)
DATA4 DB 10H DUP(1)
...
MOV DATA3[SI], AL ; 将AL的内容送入从DATA3开始再偏移(SI)的存储单元中
ADD DX, DATA4[BX][DI] ; 将从DATA4开始再偏移(BX)+(DI)的字存储单元的
; 内容与DX的内容相加,结果送回DX中
② 在指示性语句中引用
若直接引用变量名,则表示该操作数为存储器操作数,其表现形式为:段地址:[ 偏移地址 ] 。
[ ] 既指明该操作数为存储器操作数又有加号的作用。
NUM DB 75H
ARRAY DW 20H DUP(0)
ADR1 DW NUM ; 表示取偏移地址
ADR2 DW ARRAY[2] ; 表示取偏移地址
ADR3 DD NUM ; 低字节取偏移地址,高字节取段地址
4. 属性定义伪指令 LABEL
LABEL 对属性进行永久性修改,PTR 对属性进行暂时性修改。
应用举例:
SUB1_FAR LABEL FAR
SUB1: MOV AX, 30H
...
- SUB1_FAR 与 SUB1 两个标号具有相同的逻辑地址。
- SUB1_FAR 与 SUB1 被转移指令或调用指令使用时是指同一个入口地址。
- SUB1 只能被段内调用,SUB1_FAR 可以被段间指令调用。
DATA_BYTE LABEL BYTE
DATA_WORD DW 20H DUP(?)
- DATA_BYTE 与 DATA_WORD 具有相同的段基址和偏移量。
-
DATA_BYTE 可以被用来存取一个字节数据,而 DATA_WORD 则不能。
5. 表达式运算符
① 算术运算符:+、-、*、/、MOD
MOV AL, 8 + 5
MOV AX, NUM + (9 - 1) * 2 ; 若NUM EQU 10,则10+16
; 若NUM为变量名,则其偏移地址+16
② 逻辑运算符:AND、OR、NOT、XOR
用于对数值进行的按位逻辑运算并得到一个确定的数值结果。
MOV AX, 0ADH AND 0CCH
③ 关系运算符:用来比较两个表达式的大小。
EQ(等于)、NE(不等于)、LT(小于)、 LE(小于等于)、GT(大于)、 GE(大于等于)
关系运算符比较的两个表达式必须 同为常数或同一逻辑段中的变量 。
- 若是常量的比较,则按无符号数进行比较。
- 若是变量的比较,则比较它们的偏移量的大小。
关系运算的结果只能是 “真” 或 “假”,即全 1 或全 0 。
MOV AX, 0FH EQ 1111B ; 等价于MOV AX, 0FFFFH
MOV BX, OFH NE 1111B ; 等价于MOV BX, 0
VAR DW NUM LT OABH ; 该语句在汇编时,根据符号常量NUM的大小来决定VAR存储单元的值。
; 当NUM<0ABH时,变量VAR的内容为0FFFFH;否则,VAR的内容为0。
④ 取值运算符
- OFFSET:得到标号或变量的偏移地址。
- SEG:得到标号或变量的段地址。
MOV BX, OFFSET DMem1 ; 等同于LEA BX, DMem1
MOV AX, SEG DMem1 ; 段关联时
MOV DS, AX
⑤ 属性运算符
格式:类型 PTR 表达式
类型可以是 BYTE、WORD、DWORD、NEAR 和 FAR 。
功能:将表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为 “类型” 所指的值。这种修改是临时的,只在含有该运算符的语句内有效。
MOV AX, WORD PTR DMem1
JMP FAR PTR LAB1
⑥ 其它运算符
二、符号定义伪指令
符号定义伪指令将常数或表达式等形式用某个指定的符号来表示。
格式:符号名 EQU 表达式
功能:用符号名来表示 EQU 右边的表达式。后面的程序中一旦出现该符号名,汇编程序就把它替换成该表达式。
① 常数或数值表达式
COUNT EQU 5
NUM EQU COUNT+6
② 地址表达式
ADR1 EQU DS:[BP+14]
③ 变量、寄存器名或指令助记符
CRE EQU CX
在同一源程序中,同一符号不能用 EQU 定义多次。
CBD EQU DAA
CBD EQU ADD ; 错误。