汇编语言程序的基本结构与组成
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本章主要介绍了汇编语言程序的基本结构与组成、伪指令及其使用方法、D O S功能调用和B I O S功能调用,以及汇编语言程序设计的基本技术。
本章还给出了汇编语言程序上机和调试的实例。
通过该实例,可以了解汇编语言程序设计与开发的全过程。
本章中介绍的程序设计技术包括简单程序设计、分支程序设计、循环程序设计和子程序设计,每种程序设计均给出了多个具体实例,并对设计思想进行了分析,提供了有价值的程序设计技术和方法。
使用这些技术和方法可以为PC机开发基于汇编语言的软件。
6.1汇编语言与汇编程序
6.1.1汇编语言的基本概念
1.机器语言与汇编语言(M a c h i n e L a n g u a g e a n d A s s e m b l y L a n g u a g e)
计算机程序由一系列指令序列组成。
计算机通过对每条指令的译码和执行来完成相应的操作。
指令必须以二进制代码的形式存放在内存中,才能够被计算机所识别和理解,并加以执行。
由二进制代码表示的指令称为机器指令,相应的程序称为机器语言程序。
机器语言程序由0、1二进制代码组成,不便于编程和记忆。
由此产生了用指令助记符表示的汇编语言指令,对应的程序称为汇编语言程序。
例6-1将4位二进制数转换为A S C I I码字符。
当数在0000B-1001B时,对应的A S C I I 码为‘0’-‘9’;当数在1010B-1111B时,对应的A S C I I码为‘A’-‘F’。
设待转换的数据已在累加器A L中(低4位)。
8086汇编语言程序如下:
A N D A L,0F H
C M P A L,0A H
J B N U M
A D D A L,07H
N U M:A D D A L,30H
R E T
对例6-1程序进行汇编以后,得到8086汇编指令对应的机器代码(用十六进制数表示),如表6.1所示。
在表6.1中,第一列表示机器代码存放的内存地址,该地址与机器所处的环境有关;第二列表示8086机器代码,每条指令的机器代码由一个或几个字节组成;第三列表示汇编指令,由指令助记符和操作数组成。
指令前可能有标号,表示该指令第一个字节所在的地址。
表6.1汇编后的机器代码
地 址 机器代码 对应的汇编指令
E380:0000240F A N D A L,0F H
E380:00023C0A C M P A L,0A H
E380:00047202J B N U M
E380:00060407A D D A L,07H
E380:00080430N U M:A D D A L,30H
E380:000A C3R E T
2.汇编语言与高级语言(A s s e m b l y L a n g u a g e a n d C o m p u t e r-i n d e p e n d e n t L a n g u a g e)从例6-1可见,汇编语言程序的基本单位仍然是机器指令,只是采用助记符表示,便于人们记忆。
因此汇编语言是一种依赖于计算机微处理器的语言,每种机器都有它专用的
汇编语言(如8086C P U与8031单片机的汇编语言即不相同),故汇编语言一般不具有通用性和可移植性。
由于进行汇编语言程序设计必须熟悉机器的硬件资源和软件资源,因此具有较大的难度和复杂性。
高级语言,如B A S I C,F O R T R A N,C语言等是面向过程的语言,不依赖于机器,因而具有很好的通用性和可移植性,并且具有很高的程序设计效率,便于开发复杂庞大的软件系统。
既然高级语言有很多优点,为什么还要学习汇编语言呢?理由如下:
⑴ 汇编语言仍然是各种系统软件(如操作系统)设计的基本语言。
利用汇编语言可以设计出效率极高的核心底层程序,如设备驱动程序。
迄今在许多高级应用编程中,32位汇编语言编程仍然占有较大的市场。
⑵ 用汇编语言编写的程序一般比用高级语言编写的程序执行得快,且所占内存较少。
⑶ 汇编语言程序能够直接有效地利用机器硬件资源,在一些实时控制系统中更是不可缺少和代替。
⑷ 学习汇编语言对于理解和掌握计算机硬件组成及工作原理是十分重要的,也是进行计算机应用系统设计的先决条件。
6.1.2汇编语言源程序的组成
1.汇编语言源程序的结构(P r o g r a m S t r u c t u r e)
例6-2将一个8位二进制数分成高4位和低4位分别转换为两个A S C I I字符。
设待转换的数据及转换好的A S C I I字符均存放在数据段中。
完整的汇编语言源程序如下:
N A M E H E X T O A S C
;*********************************************************
D A T A S
E G M E N T;数据段定义开始
H E X D B5A H
A S C D B2D U P(?)
D A T A
E N D S;数据段定义结束
;*********************************************************
;*********************************************************
S T A C K S E G M E N T;堆栈段定义开始
D B256D U P('S')
T O P E Q U$-S T A C K
S T A C K E N D S;堆栈段定义结束
;*********************************************************
;*********************************************************
C O
D
E S E G M E N T;代码段定义开始
A S S U M E C S:C O D E,D S:D A T A,S S:S T A C K ;.........................................................
S T A R T:M O V A X,D A T A;主程序开始
M O V D S,A X
M O V A X,S T A C K
M O V S S,A X
M O V S P,T O P
M O V B X,O F F S E T A S C
M O V A L,H E X
M O V A H,A L
M O V C L,4
S H R A L,C L
C A L L N E A R P T R C O N V E R T
M O V[B X],A L
I N C B X
M O V A L,A H
C A L L N E A R P T R C O N V E R T
M O V[B X],A L
H L T;主程序结束 ;.........................................................
C O N V E R T P R O C;过程(子程序)定义开始
A N D A L,0F H
C M P A L,10
J B N U M
A D D A L,7
N U M:A D D A L,'0'
R E T
C O N V E R T E N
D P;过程(子程序)定义结束 ;.........................................................
C O
D
E E N D S;代码段定义结束
;*********************************************************
E N D S T A R T;程序结束
从例6-2中可以看出,汇编语言源程序一般包括了数据段、堆栈段和代码段,即程序由段结构组成。
它们由段定义开始语句“S E G M E N T”和段定义结束语句“E N D S”来定义一个段。
每个段都有一个段名,段名可自由选取,如数据段的段名为“D A T A”,堆栈段的段名为“S T A C K”,代码段的段名为“C O D E”。
数据段、堆栈段和代码段的作用各不相同。
数据段用于存放变量、数据和结果,堆栈段用于执行压栈和弹栈操作,以及子程序调用和参数传递,代码段则是所编制的执行程序或常数表格。
各个段都由一系列语句组成。
语句包括指令语句和伪指令语句。
指令语句(I n s t r u c t i o n S t a t e m e n t s)产生对应的机器代码,指定C P U做什么操作,而伪指令语句(D i r e c t i v e S t a t e m e n t s)并不产生机器代码,仅仅起控制汇编过程的作用,它指定汇编器(A s s e m b l e r)作何种操作。
汇编器是专门把汇编语言源程序汇编成机器语言的工具软件。
它通过伪指令来了解诸如“变量名列表”、“变量所在位置”、“过程名”等信息。
在例6-2中,N A M E,S E G M E N T/E N D S,D B,E Q U,O R G,A S S U M E,P T R,P R O C/E N D P,E N D等都是伪指令,它们是汇编语言源程序的重要组成部分。
2.汇编语言的语句格式(S t a t e m e n t F o r m a t s)
汇编语言程序的每行语句由1~4个部分组成。
指令语句和伪指令语句在格式上稍有区别,指令语句的标号后有冒号“:”,而伪指令语句的标号后则没有冒号。
指令语句的格式为
[L A B E L:]O P E R A T I O N[O P E R A N D][;C O M M E N T]
标号域 指令助记符域 操作数域 注释域
伪指令语句的格式为
[L A B E L]O P E R A T I O N[O P E R A N D][;C O M M E N T]
标号域 伪指令助记符域 操作数域 注释域
语句格式中用方括号括起来的部分,可以有也可以没有。
每部分之间用空格(至少一个)分开,一行最多可有132个字符。
L A B E L:标号域,表示段名、变量名、过程名或指令符号地址等。
O P E R A T I O N:助记符域,为指令或伪指令的助记符。
O P E R A N D:操作数域,表示操作的对象,由一个或多个表达式组成,表达式与表达式之间必须用逗号“,”分开。
C O M M E N T:注释域,用来说明语句的功能,以“;”开始。
汇编程序对“;”以后的部分不予汇编。
指令助记符前面还可以有[前缀]。
汇编程序语句中的四个域,均可以用大写、小写或大小写混合编写。
3.标号(L a b e l)
标号是一个自行设计的标识符或名称,最多可由31个字母、数字和特别字符(?、@、_、$)等组成。
但不能用数字开头,中间不能有空格,也不能为汇编语言的保留字。
注:保留字指有专门用途的字符或字符串,如C P U的寄存器名、指令助记符、伪指令助记符等。
标号一般表示变量名、段名、过程名或指令符号地址。
变量名、段名和过程名由专门的伪指令语句定义,而指令符号地址则根据需要在标号域中写上,后面跟一个“:”。
在同一个汇编单位(以E N D结束的程序模块)中,标号域中的标号不能相同。
4.操作数域(O p e r a n d F i e l d s)
操作数可以是常数、变量、标号、寄存器名或表达式。
⑴ 常数:
汇编语言语句中出现的常数一般有5种:
① 二进制数 后跟字母B,如01001001B。
② 八进制数 后跟字母Q,如276Q。
③ 十进制数 后跟字母D或不跟字母,如10D或10。
④ 十六进制数 后跟字母H,如0F H,30H。
注意,当数字的第一个字符是A~F时,在字符前应添加一个数字0,以示和变量或保留字的区别。
如0A H表示十六进制数,而A H 则表示8086C P U中的8位寄存器。
⑤ 字符和字符串 字符或字符串的值是取其对应的A S C I I码,并规定用一对单引号’ ’括起来。
如字符’0’,其对应的A S C I I码为30H。
字符串’A S M’以ASCII码41H、53H和4DH 存放。
(2)变量、标号和寄存器名
例如,指令M O V A L,H E X中,A L为寄存器名,表示目的操作数,H E X为变量名,表示源操作数。
(3)表达式
由运算符连接起来的式子叫表达式,汇编程序在对其汇编时,按一定的规则对表达式进行运算后得到一个数值或一个地址。
表达式可分算术表达式、逻辑表达式、关系运算表达式、分析运算表达式和合成运算表达式。
① 算术表达式
算术运算符有
加(+)、减(-)、乘(*)、除(/)、求余(M O D)
算术运算表达式的最后结果仍为一个数。
例如
5*8+30, 128/100,206M O D128
等算术表达式,其结果分别为70,1和78。
② 逻辑表达式
逻辑运算符有
A N D----逻辑与
O R-----逻辑或
X O R----逻辑异或
N O T----逻辑非
逻辑表达式的结果视情况不同而可能为8位或16位二进制数。
逻辑运算符与逻辑运算指令的区别在于,前者在汇编时完成逻辑运算,而后者在指令执行时完成逻辑运算。
例如
A N D A L,10101010
B A N D0F H
10101010B A N D0F H为逻辑表达式,其结果在汇编时即已确定,为00001010B,故上述指令等价于
A N D A L,00001010B
③ 关系表达式
关系运算符有
等于(E Q)、不等于(N E)、小于(L T)、大于(G T)、大于等于(G E)、小于等于(L E)。
若关系成立,则结果为真(0F F F F H);否则为假(0000H)。
例如指令
M O V B X,5G T3
中,5G T3为关系表达式,该关系成立,结果为0F F F F H。
故指令等价于
M O V B X,0F F F F H
④ 分析运算表达式和合成运算表达式
分析运算表达式和合成运算表达式的操作对象都为存储器操作数。
存储器操作数表示变量、符号地址、存储单元等。
分析运算表达式把存储器操作数分解为几个部分,如分解出段值、偏移量、类型等;而合成运算表达式则把这些组成部分综合为存储器操作数。
例如,例6-2中的指令
M O V B X,O F F S E T A S C
O F F S E T A S C即为分析运算表达式,它的作用为取存储器操作数(变量)A S C的地址偏移量,由于在例6-2中,A S C的偏移地址为0001H,即O F F S E T A S C=0001H。
故该指令等价于 M O V B X,0001H
6.2伪指令及其应用
如前所述,伪指令语句只是用来指示、引导汇编程序在汇编时做一些操作,它不产生机器代码,本身也不占用存储单元。
伪指令主要分为下列几类:
----程序分段及存储器分配
----变量定义及存储器申请
----过程定义
----符号定义
----程序模块定义与通信
----宏定义及宏调用
----条件汇编
----格式控制,列表及其他功能
6.2.1段定义伪指令S E G M E N T/E N D S
1.S E G M E N T和E N D S
S E G M E N T和E N D S为程序分段的定义,其格式如下:
[段名]S E G M E N T[定位方式][组合方式][类别名]
指令语句或伪指令语句
[段名]E N D S
⑴ 段名
段名是赋予该段的一个名称,它位于S E G M E N T与E N D S伪指令之前,成对出现,且前后必须一致。
段名的取法与标号、变量名等相同。
在同一个模块中,不同段的段名不能相同。
段名代表该段的段地址。
例如,例6-2中的指令:
M O V A X,D A T A
M O V D S,A X
表示取数据段的段地址(用段名表示)送A X,然后再将A X(段地址)送数据段寄存器D S。
⑵ 定位方式
程序的段必须连续放置在内存单元的某个区域,并占据一定的存储空间。
为了对程序的段进行合理的管理,需要对段放置的起始地址进行规定,这就是定位方式的作用。
有4种定位类型:B Y T E、W O R D、P A R A、P A G E。
起始地址分别为(X表示可为0或1):
B Y T E X X X X X X X X X X X X X X X X X X X X B
W O R D X X X X X X X X X X X X X X X X X X X0B
P A R A X X X X X X X X X X X X X X X X0000B
P A G E X X X X X X X X X X X X00000000B
分别表示以字节、字、节、页的边界为起始地址。
如果缺省定位方式,则以节(P A R A)的边界为起始地址。
一节包含16个连续的字节单元,一页包含256个连续的字节单元。
⑶ 组合方式
对于规模较大的程序,常将程序分割为多个模块。
在不同的模块中,段名可以相同,组合方式的作用是指示连接程序,把同名的段按照指定的方式组合起来形成一个新的段。
组合方式共有6种。
① N O N E:表示该段与其他模块的段没有任何关系,每段都有自己的基址。
这是缺省方式。
② P U B L I C:表示该段与其它模块中说明为P U B L I C方式的同名段互相组合成一个逻辑段,逻辑段的长度为各段长度之和。
③ S T A C K:表示此段为堆栈段,连接时把所有S T A C K方式的同名段连接成一个段,由S S指向该段的起始地址。
④ C O M M O N:表示该段与其它模块中所有已说明为C O M M O N的同名段共享相同的存储区域,共享的长度为模块同名段中最大长度,各共享段具有相同的段起始地址。
⑤ M E M O R Y方式:表示该段应定位在所有其他段的上面。
若有多个段选用M E M O R Y,则除第一个之外,其余段均作为C O M M O N处理。
⑥ A T:表示该段按绝对地址定位,其段地址即为其后表达式的值,位移量为0。
⑷ 类别名
类别名必须用单引号括起来。
连接程序把类别名相同的所有段放在连续的存储区域内,先出现的段放前,后出现的在后,但对各段不进行重新组合。
一般总是定义堆栈段的类别名为‘S T A C K’,例如,例6-2中,堆栈段可定义如下:
S T A C K S E G M E N T P A R A S T A C K‘S T A C K’
表示堆栈段从节的起始地址开始存放,组合方式为S T A C K,类别名为‘S T A C K’。
2.G R O U P伪指令
前述的组合方式是把同名的段按照指定的方式组合起来形成一个新的段,而G R O U P伪指令则用来把模块中若干不同名的段集合成一个组,使其装入同一个物理段中,组内各段之间的跳转可视为段内跳转。
格式如下:
[组名]G R O U P[段名][,…]
注:组名与段名是一样的取名规则,是代表该组的段地址,格式中的段名也可用表达式S E G[变量]或 S E G[标号]来代替,其中“S E G”运算符表示取变量或标号的段地址。
6.2.2位置计数器$和定位伪指令O R G
1.位置计数器$
在汇编过程中,汇编程序专门设置了一个表示当前位置的计数器,称位置计数器$。
正常情况下,汇编程序每扫描一个字节,位置计数器的值即加1。
例6-2中,语句 T O P E Q U$-S T A C K
表示当前位置计数器的值$减去S T A C K代表的起始位置的值,然后把两者的差值赋予符号常量T O P。
本例中,T O P的值为256。
又如
J M P$
表示程序跳转到本条指令,即进入死循环状态。
该语句一般用于等待中断的发生。
2.O R G伪指令
O R G伪指令把数据表达式的值赋予位置计数器。
通过O R G伪指令,可以将位置计数器设置为新值,以便其后的指令性语句或数据定义语句从指定的位置处进行汇编。
O R G伪指令格式为:
O R G[数据表达式]
例如,例6-2中变量H E X的原来位置为数据段中0000H单元,现将该变量改放到0100H 单元:
O R G0100H
H E X D B5A H
6.2.3段寻址伪指令A S S U M E
S E G M E N T/E N D S可以用来定义不同的段。
尽管取了一些意义明显的段名,如D A T A,C O D E,S T A C K等,但汇编程序仍然不知道哪个对应数据段,哪个对应代码段,哪个对应堆栈段。
因此,用A S S U M E伪指令来说明段寄存器与段名之间的对应关系,以便能够正确汇编。
A S S U M E语句的一般格式为:
A S S U M E段寄存器:段名 [,段寄存器:段名][,…]
其中段寄存器有C S、D S、E S、S S。
每个指定之间用逗号分开。
例如,例6-2中段的说明语句为:
A S S U M E C S:C O D E,D S:D A T A,S S:S T A C K
表示C O D E为代码段,D A T A为数据段,S T A C K为堆栈段。
该程序中没有用到附加段。
注意,A S S U M E语句只是对各段的性质进行了说明,并未向各个段寄存器真正赋值。
要向各个段寄存器赋值,必须在程序中用指令语句实现。
例如,用下列指令向S S赋值:
M O V A X,S T A C K
M O V S S,A X
6.2.4过程定义伪指令P R O C/E N D P
过程即是子程序。
汇编语言规定必须对过程进行定义,以确定过程的三种属性。
过程的属性确定之后,就可对调用指令C A L L进行正确汇编,决定是产生近调用指令还是远调用指令。
近调用时,只需将返回位置的偏移地址压栈,而远调用时,需将返回位置的偏移地址和段地址都压入堆栈。
1.过程的三种属性
① 段属性:过程所在段的段地址。
② 偏移量属性:过程所处位置的段内偏移地址。
③ 类型属性(N E A R和F A R)。
过程为N E A R或F A R类型。
N E A R----近过程。
该过程与调用指令C A L L处在同一个代码段中(段名相同)。
F A R----远过程。
该过程与调用指令C A L L处在不同的代码段中(段名不同)。
2.过程的定义
过程定义的格式如下:
过程名 P R O C N E A R/F A R
语句
……
R E T
过程名 E N D P
其中过程名是为该过程指定的一个名称,与变量、标号的定义法相同。
P R O C/E N D P必须成对出现。
编写过程时,最后一条指令必须是返回指令R E T。
它将堆栈内保存的返回地址弹出,以实现程序的正确返回。
6.2.5数据定义伪指令与存储器分配
1.变量的三种属性
变量均有下列三种属性。
①段属性:变量所在段的段地址。
如例6-2中的变量H E X和A S C,它们都处在同一个数据段中,故有相同的段地址。
②偏移属性:变量所处位置的段内偏移地址。
例如变量H E X的偏移量为0000H,A S C 的偏移量为0001H。
③类型属性:变量为字节、字或双字类型。
D B—定义字节型变量,每个变量分配1个存储单元
D W--定义字型变量,每个变量分配2个存储单元
D D--定义双字型变量,每个变量分配4个存储单元
例6-2中,变量H E X和A S C均为字节型变量,各分配一个存储单元。
2.变量定义及存储器申请伪指令D B/D W/D D
⑴ 格式1
[变量名]{D B/D W/D D} 表达式
功能:定义一变量,并为其分配一定数量的存储单元,变量的初值由表达式的值指定。
若初值可任意,则用问号(?)表示。
变量名可省。
例如,语句
H E X D B5A H
定义了一个字节变量,并分配一个存储单元,其初值为5A H。
语句
V W O R D D W1234H
定义了一个字型变量,并分配2个存储单元,其初值为1234H。
在存放字变量时,低字节在前,高字节在后。
存储单元依次赋给初值为:34H,12H。
语句
B U F F E R D W1,0,-1
定义了三个字单元,并初始化为:01H,00H,00H,00H,0F F H,0F F H。
语句
S T R D B‘P r o g r a m’
定义了一个字符串,并以字符的A S C I I码依次存放:50H,72H,6F H,67H,72H,61H,6D H。
语句
H E X_O F F D W H E X
定义了一个字单元,其初值为已定义变量H E X的偏移量。
注意,本语句中,不是把H E X的初值赋予变量H E X_O F F,而是取变量H E X的偏移地址赋予H E X_O F F。
语句
D D V A R D D1*******H
定义了一个双字单元,其初值为12345678H,在内存中按下列次序存放:78H,56H,34H,12H。
⑵ 格式2
[变量名]{D B/D W/D D} D U P(表达式)
这种格式用于定义一些重复的数据或分配一数据块空间。
例如
A S C D B2D U P(?)
分配2个字节单元,初值任意。
语句
B U F D W100D U P(0)
分配100个字单元,初值为0。
实际占用200个字节单元。
D U P操作符可以嵌套,如:
Z I P D B3D U P(0,2D U P(1))
存储单元依次初始化为:0,1,1,0,1,1,0,1,1。
3.变量的使用
经过变量定义及存储器申请之后,在程序中即可像高级语言一样使用变量。
例如 M O V A L,H E X
表示取变量H E X的内容送A L寄存器。
而指令
M O V A S C[B X],A L
表示取变量A S C的偏移地址,再与B X寄存器的内容相加,得到存储器操作数的有效地址即E A,再将A L寄存器的内容送入该单元。
若B X=0,则数据被送往A S C所在单元。
6.2.6记录与结构定义伪指令(R E C O R D、S T R U C/E N D S)
1.记录定义伪指令R E C O R D
记录是汇编语言的一种特殊数据类型。
记录的长度固定,为8位或16位二进制数。
记录中相邻的若干位称为一个字段。
要使用记录,首先要定义记录的类型,然后定义记录型变量,并分配存储单元,最后配合某些专用的操作符使用记录。
⑴ 记录类型的定义
在所有段定义语句之前定义记录类型,其格式如下:
记录名 R E C O R D字段名:宽度[=初值表达式],…
记录名和字段名遵循标号的取名法则。
宽度表示该字段占有的二进制位数,最多不能超过16位,初值表达式可省,表示该字段的初值。
例如
C O L O R R E C O R
D X:3=5,Y:4=12,Z:9=255
定义了一个记录类型,记录名为C O L O R,包含了三个字段X,Y,Z,宽度分别为3位、4位和9位,总宽度为16位。
字段初值分别为5,12和255,如下所示。
位 1514131211109876543210
初值 1011100011111111字段 X Y Z
当定义中的字段总位数不能占满整个字节或字时,汇编程序就把所定义的字段与记录的低位端对齐。
例如
C O O L R E C O R
D A:5=17,B:7=127
定义了12位宽,向低端对齐,高4位未定义,如下所示。
位 1514131211109876543210初值 100011111111字段 未定义 A B
⑵ 记录类型变量的定义及存储器分配
一般在数据段中定义记录类型变量,其格式如下:
[变量名]记录名 <[字段值表]>
变量名即为该记录类型的变量名,它可省缺;字段值表是给字段赋初值,中间用逗号','分开,其字段值的排列顺序及大小应与该记录说明时各字段相一致;如果记录变量的某字段用其说明时的缺省值,那么,可用逗号来表示;如果所有字段都如此,则可省去字段值表,但必须保留一对尖括号"<"、">"。
例如
C O L O R1C O L O R<,15,9>
定义了一个记录型变量,其字段X、Y和Z的初值分别为5(缺省值),15和9。
(3)记录的使用
定义了记录型变量之后,在程序中可像一个字节或字型变量来使用。
如
M O V D X, C O L O R1
指令执行后,D X=1011,1110,0000,1001B=B E09H
⑷ 记录专用操作符
① M A S K操作符
它的操作对象为记录的字段名,结果是字段名所在位置的位全为1,其余为0。
例如
A N D D X, M A S K Z
M A S K Z使得Z字段的所有位为1,其余位为0,结果M A S K Z=0000,0001,1111,1111B=01F F H。
② W I D T H操作符
W I D T H操作符返回的是纪录或纪录中字段的位数。
2.结构定义伪指令S T R U C/E N D S
结构是一种复杂的数据类型。
结构体中包含若干个字段,其数据类型一般为基本的数据类型。
像记录一样,要使用结构,首先要定义结构类型,然后定义结构型变量,并分配存储单元,最后采用“.”运算符访问结构体中的字段。
⑴ 结构类型的定义
在所有段定义语句之前定义结构类型,其格式如下:
结构名 S T R U C
……
[字段名1]{D B/D W/D D}表达式
[字段名2]{D B/D W/D D}表达式
……
结构名 E N D S
表达式中可以包含D U P在内的重复操作符。
例如
C O U R S E S T R U C
N O D D?
C N A M E
D B'A s s e m b l e r’
S C O R E D W0
C O U R S E E N
D S
定义了结构名为C O U R S E的结构,该结构包含三个成员变量,结构体长度为15(=4+9+2)个字节。
⑵ 结构类型变量的定义及存储器分配
一般在数据段中定义结构类型变量,其格式如下:
[变量名]结构名 <[字段值表]>
例如,定义一个结构变量C O U R S E1,其初值为缺省。
C O U R S E1C O U R S E<>
(3)结构的使用
定义了结构型变量之后,在程序中即可使用,格式如下:
结构变量名.字段名
例如
M O V A X,C O U R S E1.S C O R E
表示取结构变量C O U R S E1的S C O R E字段值。
6.2.7符号定义伪指令(E Q U、L A B E L)
1.E Q U伪指令
E Q U伪指令为常量、变量、表达式或其他符号定义一个名字,但不分配内存空间,格式如下:
符号名 E Q U数值表达式
例如
T H R E E E Q U3;标号T H R E E代表数值3
T O P E Q U$-S T A C K
注 ① 使用E Q U可使程序简单明了,便于修改。
②“=”伪操作与E Q U功能相似,但“=”语句可重复定义,而E Q U不能。
③ E Q U可用P U R G E解除,以便重新赋予新的数值。
2.L A B E L伪指令
L A B E L伪指令为当前存储单元定义一个指定类型的变量名或标号,变量名的类型为
B Y T E、W O R D、D W O R D,标号的类型为N E A R和F A R。
格式如下:
变量名/标号 L A B E L[类型]
例如
B Y T E_A R R A Y L A B E L B Y T E
W O R D_A R R A Y D W50D U P(?)
第二条语句定义了一个字型数组变量W O R D_A R R A Y,有50个字单元,100个字节。
如程序中同样想把这些单元作为字节单元使用,则采用第一条语句,即定义一个字节型数组变量
B Y T E_A R R A Y,程序可采用下列指令访问存储单元:
M O V A L,B Y T E_A R R A Y[2];将2号字节单元内容送A L
M O V A X,W O R D_A R R A Y[0];将0号字单元内容送A X
又如,若过程T R A N S既要适合远调用,也要适合近调用,可采用如下语句:
T R A N S_N L A B E L N E A R
T R A N S P R O C F A R
这样,远调用时采用标号T R A N S,近调用时则采用标号T R A N S_N。
6.2.8程序模块定义伪指令(N A M E/E N D、P U B L I C/E X T R N)
汇编语言程序可划分为许多模块,对每个模块独立地进行汇编,然后连接形成可执行文件。
1.N A M E/E N D伪指令
N A M E/E N D伪指令定义一个模块,作为一个独立的汇编单位,汇编处理只进行到模块结束语句E N D为止。
N A M E缺省时模块若使用了T I T L E语句,则T I T L E语句中前6个字符为模块名,否则源文件名将作为模块名。
格式如下:
N A M E模块名
…….
E N D标号
2.P U B L I C伪指令
P U B L I C伪指令用来说明本模块中被定义的哪些符号(常量、变量、标号、过程名)可以被其他模块所引用,格式如下:
P U B L I C[符号名表]
例如,在模块A中,定义了字型变量A B C,常量B C D,近过程C D E,它们将在其它模块中被引用,则在模块A中需做如下说明:
P U B L I C A B C,B C D,C D E
3.E X T R N伪指令
E X T R N伪指令用来说明本模块中哪些符号(常量、变量、标号、过程名)是引用其它模块已经被P U B L I C所说明的,格式如下:
E X T R N[符号:类型,…]
符号的类型可为B Y T E、W O R D、D W O R D、N E A R、F A R和A B S(符号常量)等,必须与它们在其他模块中定义的类型一致。
例如,在模块B中对模块A中的上述符号进行引用,语句为:
E X T R N A B C:W O R D,B C D:A B S,C D E:N E A R
6.3汇编语言属性操作符
6.3.1分析操作符(S E G、O F F S E T、T Y P E、L E N G T H、S I Z E)
1.分析操作符(数值返回操作符)
分析操作符的操作对象是变量或标号,返回的是变量或标号的段地址、偏移地址及类型的属性值,其运算的结果为一常数。
格式为:
分析运算符 变量或标号
⑴ S E G运算符
功能:分离出该变量或标号的段基址。
如:
M O V A X, S E G H E X该指令等价于
M O V A X, D A T A其中D A T A为段名,也表示段地址。
⑵ O F F S E T运算符
功能:分离出该变量或标号的偏移地址。
如:
M O V B X, O F F S E T A S C该指令等价于。