汇编语言程序语句除指令以外还可以由伪操作和
宏指令组成·它不像
机器指令那样是在程序运行期间由计算机来执行的,它是在
汇编程序对
源程序汇编期间由汇编程序处理的操作,它们可以完成如数据定义、分配存储区、指示程序结束等功能。
伪操作一类
数据定义及存储器分配伪操作
这一类伪操作的格式是:
[Variable] Mnemonic Operand,...,Operand[;Comments]
其中
变量(Variable)字段是可有可无的,它用符号地址表示,其作用与指令语句前的标号相同,但它的后面不跟冒号.如果语句中有变量则
汇编程序使其记以第一个字节的
偏移地址.
注释(Comments)字段用来说明该伪操作的功能,它也是可有可无的.
助记符(Mnemonic)字段说明所用伪操作的助记符,常用的有以下几种:
DB伪操作用来定义
字节,其后的每个
操作数都占有一个字节.
DW伪操作用来定义字,其后的每个
操作数都占有一个字(低位
字节在第一个字节地址中,高位字节在第二个字节地址中).
DD伪操作用来定义双字,其后的每个
操作数占有二个字.
DQ伪操作用来定义四个字,其后的每个操作占有四个字.
DT伪操作用来定义十个字节(五个字),其后的每个
操作数占有十个字节,形成压缩的BCD码.
操作数字段还可以使用复制操作符(duplication opreator)来复制某个操作数,例:
ARRAY1 DB 2 DUP(0,1,2,?)
注1:使用PTR属性操作符,可以指定
操作数的类型属性.
例:
MOV AX,WORD PTR OPER1
注2:使用LABEL伪操作可以使同一
变量具有不同的类型属性.
例:
BYTE_ARRAY LABEL BYTE
WORD_ARRAY DW 50 DUP(?)
伪操作二类
表达式赋值伪操作EQU
例:
CONST EQU 256 数赋以符号名
DATA EQU HEIGHT+12 地址表达式赋以符号名
ALPHA EQU 7
BETA EQU ALPHA-2
P8 EQU DS:[BP+8]
另有一个与EQU类似的=伪操作也可以作为赋值操作使用.这们之间的区别是EQU伪操作中的
表达式名是不允许重复定义的,而=伪操作则允许重复定义.
例:
EMP=7
EMP=EMP+1
伪操作三类
段定义伪操作
存储器的物理地址是由
段地址和
偏移地址组合而成的,
汇编程序在把
源程序转换为
目标程序时,必须确定标号和
变量的偏移地址,并且需要把有关信息通过目标模块传送给
连接程序,以便连接程序把不同的段和模块连接在一起形成一个可执行程序.为此,需要用到段定义伪操作,段定义伪操作的格式如下:
segment_name SEGMENT
...
segment_name ENDS
其中删节号部分,对于
数据段、附加段和
堆栈段来说,一般是
存储单元的定义、分配等伪操作;对于
代码段则是指令及伪操作。
此外,还必须明确段和段寄
存储器的关系,这可用ASSUME伪操作来实现,其格式为:
ASSUME assignment,...,assignment
其中assignment说明分配情况,其格式为:
segment_register_name:segment_name
其中
段寄存器名必须是CS、DS、ES和SS中的一个,而段名必须是由SEGMENT定义的段中的段名。而ASSUME NOTHING则可取消前面由ASSUME所指定的
段寄存器。
由于ASSUME伪操作只是指定某个段分配给哪一个
段寄存器,它并不能把
段地址装入段寄存器中,所以在
代码段中,还必须把段地址装入相应的段寄存器中。但是,
代码段不需要这样做,代码段的这一操作是在程序初始化时完成的。
SEGMENT伪操作还可以增加类型及属性的说明,格式如下:
segname SEGMENT [align_type]
[combine_type]
[''class'']
...
segname ENDS
一般情况下,这些说明可以不用.但是,如果需要用
连接程序把本程序与其他
程序模块相连接时,就需要使用这些说明.分别叙述如下:
.定位类型(align_type)可以是:
PARA 指定段的起始地址必须从小段边界开始,即
段地址的最低的16进制数位必须为0.
BYTE 该段可以从任何地址开始
WORD 该段必须从字的边界开始,即
段地址必须为偶数
PAGE 该段必须从页的边界开始,即
段地址的最低两个16进制数位必须为0(该地址能被256整除)
.组合类型(combine_type)可以是:
PUBLIC 该段连接时将与有相同名字的其他分段连接在一起.其连接次序由连接命令指定.
COMMON 该段在连接时与其他同名分段有相同的起始地址,所以会产生覆盖.COMMON的连接长度是各分段中最大长度.
AT expression 使段的起始地址是
表达式所计算出来的16位
段地址.但它不能用来指定
代码段.
MEMORY 指定该将分配在所有其他连接在一起的段的前面(在高地址上),如果连接时有几个指定MEMORY的段,则遇到的第一个段作为MEMORY段,其他段则作为COMMON段.
.类别(''class'') 连接时用于组成段组的名字.
伪操作四类
程序开始和结束伪操作
在程序的开始可以用NAME或T99vLE为模块取名字,NAME的格式是:
NAME module_name
汇编程序将以给出的module_name作为模块的名字.如果程序中没有NAME伪操作,则也可使用T99vLE伪操作,其格式为:
T99vLE text
T99vLE伪操作可指定每一页上打印的标题.同时,如果程序中没有使用NAME伪操作,则
汇编程序将用text中的前六个
字符作为模块名.text最多可以60个字符.如果程序既无NAME又无T99vLE伪操作,则将用源程序文件名作为模块名.
表示源程序结束的伪操作的格式为:
END [label]
其中标号指示程序开始执行的起始地址.如果多个程序模块相连接,则只有主程序要使用标号,其他子程序模块则只用END而不必指定标号.
伪操作五类
对准伪操作
.EVEN伪操作使下一个字节地址成为偶数.一个字的地址最好从偶地址开始,所以对于字数组为保证其从偶地址开始,可以在它前面用EVEN伪操作来达到这一目的,例如:
DATA SEGMENT
...
EVEN
WORDAY DW 100 DUP(?)
...
DATA ENDS
.ORG Constant expression
如常数
表达式的值为n,则ORG伪操作可以使下一个字节的地址为常数表达式的值n.
地址计数器的值可以用$来表示,汇编语言允许用户直接用$来引用地址计数器的值,因此:
ORG $+8
可以表示跳过8个字节的存储区.
JMP $+2
可以表示一条空指令,该指令只是延迟处理机的一些时间,而无其他功能.
伪操作六类
基数控制伪操作
汇编程序默认的数为十进制数,因而除非专门指定,汇编程序把程序中出现的数均看作十进制数,为此,当使用其他基数表示的常数时,需要专门以标记如下:
.二进制数:由一串0、1组成其后跟以字母B,如00101100B
.十进制数:由0~9的数字组成。一般情况下后面不必加上标记,在指定其他基数的情况下,后面可跟字节字母D,如178D。
.
十六进制数:由0~9及A~F组成的数,后面跟字母H。这个数的第一个
字符必须是0~9,所以如果第一个
字符是A~F时,应在其前加上数字0,如0FFFFH。
.八进制数:由数字0~7组成的数,后面可跟字母O或Q,如1777Q。
.RADIX伪操作,可以把默认的基数改变为2~16范围内的任何基数,其格式如下:
.RADIX expression
例如:
MOV BX,OFFH
MOV BX,178
与
.RADIX 16
MOV BX,0FF
MOV BX,178D
是等价的。应当注意,在用.RADIX 16把基数定为十六进制后,十进制数后都应跟字母D。在这种情况下,如果某个
十六进制数的末字符为D,则应在其后跟字母H,以免与十进制数发生混淆。
.字符串可以看成串常,可以用单引号或双引号把字符串放在其中,得到的是字符串的ACSII值,例如:‘ABCD’。
伪操作七类
过程定义伪操作
格式为:
procedure_name PROC Attribute
.
.
.
procedure_name ENDP
其中过程名为
标识符,它又
子程序入口的符号地址,它的写法与标号的写相同.属性(Attribute)是指类型属性,它可以是NEAR或FAR.段调用使用NEAR属性,段间调用使用FAR属性