第四章 伪指令
汇编语言源程序由一系列语句构成,这些语句既可以是指令,也可以是伪指令。指令是由CPU负责执行的,每一条指令都和一条机器语言相对应。而伪指令是由汇编程序负责执行,完成一些内存单元分配、段之间的连接关系等操作,所以伪指令并不会生成机器指令,也就不会被CPU执行。在本章中,重点讲解一些常用的伪指令及其功能。
4.1伪指令的分类及伪指令语句格式
伪指令又称为伪操作,它虽然不会被CPU执行,但却可以指示汇编程序按照用户的意图,完成数据的定义、存储器的分配、指示程序结束等功能。所以伪指令在汇编语言程序设计过程中具有重要的意义,希望读者在学习过程中应该加以高度重视。
4.1.1 伪指令的分类
8088/8086的伪指令大致可分为以下八类: ·数据定义伪指令; ·符号定义伪指令; ·段定义伪指令; ·过程定义伪指令; ·结束伪指令; ·条件汇编伪指令;
·结构、记录定义伪指令; ·其他伪指令。
其中,条件汇编伪指令与结构、记录定义伪指令将在第八章予以介绍。
4.1.2 伪指令语句格式
伪指令语句格式一般由四部分组成。
语句格式: [变量] 伪指令助记符 参数1,参数2····参数n[;注释]
说明:伪指令助记符规定了伪指令的功能。一般伪指令都有参数,用于说明伪指令的操作对象,参数的类型和个数随着伪指令的不同而不同。有时参数是常数或数值表达式,有时参数是一般的符号,有时是具有特殊意义的符号。伪指令语句中的变量可有可无,如果伪指令语句中出现变量,则汇编程序使其记以第一个字节的偏移地址。注释部分也是可有可无的,用于说明该伪指令的功能。
例如 VAR1 DW 1234H,5678H ;定义VAR1为字变量
该语句中的VAR1为变量;DW为伪指令助记符;1234H与5678H为参数;分号后面给出的文字为注释。
4.2汇编语言中的数据项
数据项是指令或伪指令语句操作对象的基本组成部分。一个数据项包含有数值和属性两部分,这两部分对一条语句汇编成机器目标代码有着直接关系。
通常,汇编语言能识别的数据项有:常数、变量和标号。8086/8088汇编语言还采用了很有用的数据结构形式,例如结构和记录,可以被看成是两种特殊的变量。
4.2.1 常数
常数是没有任何属性的纯数值。在汇编期间,它的值已被完全确定,且在程序运行过程中,它也不会发生变化。
常数可以有以下类型: 1. 二进制
以字母B结尾的由0和1组成的数字序列。如10100011B。 2. 八进制
以字母O或Q结尾的由0~7组成的数字序列。如345Q。 3. 十进制
以字母D结尾的由0~9组成的数字序列。如7825D。 4. 十六进制
以字母H结尾的由0~9和A~F组成的数字序列。如12FFH。 5. 字符串常数
用单引号或双引号括起来的一个或多个字符。这些字符以其ASCII码形式存储在内存中。如‘A’,在内存中就是41H,如果是“AB”就是41H和42H组合。
说明:
(1) 在程序中,常数主要出现在以下三个地方:
①在指令语句的源操作数中作立即数使用,它应与目的操作数的位数一致,可以是8位或16位的。
例如:
MOV AL,00001111B ADD DX,0ABCDH MOV AL,‘A’
②在指令语句的mem表达式中作位移量。 例如:
MOV AX,44H[SI]
MOV DX,1234H[BX][SI]
③在伪指令定义数据语句中出现。 例如:
DB 12H ;定义一个字节数据,值为12H
DB “ABCD” ;定义四个字节的字符串数据,值为41H、42H、43H和44H DD 12345678H ;定义一个双字数据,长度为32位,值为12345678H PRICE EQU 30H ;符号PRICE等价于30H
(2) 在汇编程序中,默认基数是十进制数,即在语句中出现的十进制常数可以不在末尾加字符D,如十进制常数123D 可以写为123。当然我们可以使用“.RADIX”伪指令改变
默认的基数。例如:
.RADIX 16 ;将默认基数改变为16进制 .RADIX 2 ;将默认基数改变为2进制
4.2.2 变量
变量是代表存放在某些存储单元的符号。这些符号所代表的数据在程序运行期间随时可能变化。为了便于对变量的访问,它常常以变量名的形式出现在程序中。变量也包含数值和属性两部分。
1. 变量的定义与预置
定义变量就是给变量分配存储单元,且对这个存储单元赋予一个符号名,即变量名,同时将这些存储单元预置初值。
定义变量是用数据定义伪指令DB、DW、DD、DQ、DT等实现的。 例如:
DSEG SEGMENT VAR1 DB 12H VAR2 DB 20H VAR3 DW 1234H DSEG ENDS
经过定义的变量都有三个属性:段属性、偏移属性和类型属性。 (1)段属性(SEG)
它表示变量存放在哪一个逻辑段中(即变量所在段的段首址)。例如变量VAR1、VAR2、VAR3的三个变量都存放在DSEG数据段中,如果设DSEG数据段的段首址为1355H,则这三个变量的段属性为1355H。
注意:当在指令中要对这些变量进行操作时,事先要把它们所在段的段首址存放在某一个段寄存器(如DS)中。
(2)偏移属性(OFFSET)
变量的偏移属性指的是变量在逻辑段中离段起始的字节数。例如VAR1、VAR2、VAR3这三个变量的偏移量为00H、01H和02H。
上述段属性和偏移属性就构成了变量的逻辑地址。 (3)类型属性(TYPE)
变量的类型属性指的是变量占用存储单元的字节数。这一属性是由数据定义伪指令DB(1字节)、DW(2字节)、DD(4字节)、DQ(8字节)、DT(10字节)等来规定的。由DB定义的变量,其类型属性为1;由DW定义的变量,其类型属性为2;由DD定义的变量,其类型属性为4;由DQ定义的变量,其类型属性为8;由DT定义的变量,其类型属性为10。所以变量VAR1、VAR2、VAR3的类型属性分别为1字节、1字节和2字节。
2. 变量的使用
(1)在指令语句中的使用
要对某存储单元进行存取操作,可直接引用它的变量名。 例4-1 变量的应用。
解:在程序中直接引用变量名,其含义是访问该变量名所指向的内存单元。 程序代码编写如下: DSEG SEGMENT
VAR1 DB 12H
VAR2 DB 20H DSEG ENDS CSEG SEGMENT
ASSUME CS:CSEG,DS:DSEG START:
MOV AX,DSEG
MOV DS,AX ;将数据段DSEG的段首址送入DS寄存器 MOV BL,VAR1 ;将VAR1的内容12H送入BL寄存器 MOV DL,VAR2 ;将VAR1的内容20H送入DL寄存器 ADD BL,DL MOV AH,4CH
INT 21H ;返回DOS CSEG ENDS END START
(2)在伪指令中的应用
变量被定义后,还可以被另外的变量进行引用。引用形式有两种: ① 变量B DW 变量A ② 变量B DD 变量A
说明:对于第一种引用形式,变量B被定义为字变量,并且在语句中引用了变量A,所以变量B所指向的字单元内容就为变量A的偏移量;对于第二种引用形式,变量B被定义为双字变量,并且在语句中引用了变量A,所以变量B所指向的双字单元内容就为变量A的偏移量和段首址,其中低地址字单元存放了变量A的偏移量,高地址字单元存放了变量A的段首址。
注意:当变量引用变量时,应该使用DW和DD伪指令进行定义,而不允许使用DB、DQ、DT等伪指令。
例4-2 变量引用变量。 解:假设变量VAR1被定义成字节型变量,再定义变量VAR2为字变量,并引用变量VAR1,然后再定义变量VAR3为字变量,并引用变量VAR2,最后再定义变量VAR4为双字变量,并引用变量VAR1。那么VAR2、VAR3、VAR4这些变量的值究竟为多少。
程序代码编写如下: DSEG SEGMENT VAR1 DB 12H VAR2 DW VAR1 VAR3 DW VAR2 VAR4 DD VAR1 DSEG ENDS CSEG SEGMENT
ASSUME CS:CSEG,DS:DSEG START:
MOV AX,DSEG MOV DS,AX MOV BX,VAR2 MOV CX,VAR3
MOV DX,WORD PTR VAR4