汇编语言程序设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

汇编语⾔程序设计
第4章汇编语⾔程序设计
§4.1 汇编语⾔的模式
⼀、汇编语⾔源程序的⼀般模式
[Name 模块名]
[Title 标题]
[定义宏]
[定义数据段]
[定义附加段]
[定义堆栈段]
定义代码段
源程序结束
中括号括起的部分可以省略,可见在⼀个汇编语⾔源程序中必须要定义代码段,并且必须有源程序结束指令。

⼆、8086汇编语⾔程序的⼀个例⼦
Pg90。

§4.2 语句⾏的构成
汇编语⾔中的语句⼀般分为两种类型:指令性语句和指⽰性语句。

指令性语句的格式为:
[标号:] 助记符 [操作数1[,操作数2]] [;注释]
指⽰性语句的格式为:
[名称] 助记符 [参数1,参数2,……] [;注释]
标号和名称都是编程⼈员根据需要和⼀定的规则任意取的。

也可以认为汇编语⾔的语句⾏是由标记和分隔符(空格)构成。

⼀、标记
1.IBM宏汇编的字符集
(1)字母
(2)数字符
(3)特殊字符
2.界符
⽤于定界⼀个标记的结束或⼀个标记的开始,本⾝具有⼀定的意义。

3.常量
出现在汇编语⾔源程序中的固定值称为常量。

(1)数值常量
①⼆进制:以字母B结束。

②⼗进制:以字母D或⽆字母结束。

③⼋进制:以字母Q(或O)结束。

④⼗六进制:以字母H结束。

(2)字符常量
指⽤单引号或双引号引起的字符或字符串。

4.标识符
由程序员⾃⼰建⽴的字符序列(标号或名称)。

⼀个标识符不能超过31个字符,不能以数字开头。

5.保留字
汇编语⾔中具有特殊意义的字符序列。

6.注释
⼀⾏中分号以后的部分。

⽤于对⼀段或⼀⾏程序进⾏说明,便于阅读和理解。

⼆、符号
具有⼀定意义的字符序列。

1.寄存器名
2.变量
段属性、偏移属性、类型属性
3.标号
段属性、偏移属性、类型属性
4.常数
5.其它
三、表达式
由操作数和运算符组合⽽成的序列。

1.操作数
(1)⽴即数
(2)寄存器操作数
(3)存储器操作数
2.运算符
(1)算术运算符
+、-、*、/、MOD(求余)
(2)逻辑运算符
AND、OR、NOT、XOR
(3)关系运算符
EQ、NE、LT、LE、GT、GE
结果为“假”时,返回0,结果为“真”时,返回⼆进制全1。

§4.3 指⽰性语句
指⽰性语句不能被CPU执⾏,为编译程序服务,主要⽤于汇编语⾔源程序中的各种定义或说明。

⼀、符号定义语句
⽤于定义符号常量。

1.等值语句EQU
格式:符号名 EQU 表达式
例: PORT EQU 40H ;⽤PORT代替40H号端⼝
COUNT EQU CX ;⽤COUNT代替CX寄存器
M EQU MOV ;⽤M代替MOV指令助记符
注:EQU语句不能重新定义,即在同⼀源程序中,⽤EQU定义过的符号不能赋予不同的值。

例:B EQU [bp+8]
B EQU 20H 不⾏!
2.等号语句=
格式:符号名=表达式
功能与EQU类似。

例: PP = 89FAH ;赋值
PP = PP+1 ;PP = 89FBH
注:
等号语句与EQU语句的相同点:
符号不是变量,
所以⽤EQU、= 定义的符号不占⽤存储器单元。

区别:
等号语句可以在同⼀源程序中重复定义同⼀个符号名,⽽等值语句不⾏。

⼆、数值定义语句
⽤于定义变量,指定变量的类型和名称,并为其分配存储单元和预置初值。

1.格式:
[变量名] 数据定义符参数数1 [,参数数2,参数3……] [;注释]
说明:
变量名指⽰存储器操作数的地址(符号地址);
数据定义符指⽰存储器操作数的类型(DB字节、DW字、DD双字等);
参数数指⽰存储器操作数的内容,是赋给变量的初值。


多个相同类型的变量可在⼀条语句中定义;
⽅括号中的内容表⽰可以省略。

2.参数的形式
(1)数值常数或能产⽣数值常数的表达式
V1 DB 20,35,60
V2 DW 25*250
(2)字符或字符串
V2 DB ‘a’
V3 DB ‘a’ , ‘b’, ‘c’, ‘d’, ‘e’, ‘f’
等效于:V3 DB ‘abcdef’
当字符串长度不超过两个字符时,也可以⽤DW来定义。

V4 DW ‘ab’, ‘cd’, ‘ef’
(3)?
⼀个?号代表⼀个参数,表⽰其值不确定,不赋值,预留内存单元,以存放结果。

V5 DB ?,?
V6 DW ?
(4)DUP重复⼦句
当多个参数相同时,可⽤重复⼦句DUP来缩写:
格式:重复次数 DUP(重复内容)
V7 DB 0,0,0,0,0,0
等效于:V7 DB 6 DUP(0)
DUP⼦句可以嵌套
如:V8 DW 20 DUP(5 DUP(1,2))
3.参数在内存中的存放规则
(1)对于字节变量按顺序存放
(2)对于字变量或双字变量按低字节在低地址,⾼字节在⾼地址的原则存放。

变量名代表该变量所占内存空间第⼀个单元的偏移地址。

4.分析运算符
(1)SEG:返回⼀个变量或标号的段地址
格式:SEG 变量名(或标号)
(2)OFFSET:返回⼀个变量或标号的偏移地址
格式:OFFSET 变量名(或标号)
(3)TYPE:返回⼀个变量或标号的类型属性
格式:TYPE 变量名(或标号)
DB DW DD NEAR FAR
1 2 3 -1 -2
(4)LENGTH:返回变量定义时最外层DUP⼦句的句的重复次数,如果变量定义时未⽤DUP⼦句,则返回1。

格式:LENGTH 变量名
(5)SIZE:可以返回⼀个变量定义时所占的字节数。

格式:LENGTH 变量名
假设有⼀变量x。

则,SIZE x = TYPE x × LENGTH x
5.合成运算符
(1)PTR:临时改变⼀个存储器操作数或⼀个标号的类型属性。

格式:类型属性 PTR 存储器操作数(或标号)
对于存储器操作数,类型属性可以为:BYTE、WORD、DWORD。

对于标号,类型属性可以为:NEAR、FAR
例:
MOV BYTE PTR [BX],50
MOV WORD PTR [BX],50
JMP FAR L0
(2)THIS:永久性地为某⼀变量或标号设置⼀个新的类型属性。

格式:名称 THIS EQU THIS 类型属性
例:
V1 EQU THIS WORD
V2 DB 10H,20H
MOV AL,V2
MOV AX,V1
V1和V2指向同⼀个内在地址,V1为字属性,V2为字节属性。

L0 EQU THIS FAR
L1:……
L0和L1指向同⼀个内在地址,L0为远属性,L1为近属性。

三、段定义语句
1.格式
段名 SEGMENT
……
……
段名 ENDS
2.段指定
ASSUME 段寄存器名1:段名1,段寄存器名2:段名2,……
该语句放在代码段中的第⼀⾏,⽤于建⽴段寄存器名与段名的联系。

3.段内偏移地址指定ORG 数值表达式
⽤于指定紧跟其后的内存单元偏移地址为表达式的值。

例:
ORG 20H
V1 DW 5,10
则变量V1的偏移地址为20H。

4.段地址填装
将所定义段的段地址传送到相应的段寄存器中。

(1)代码段的段地址⾃动填装。

(2)数据段、附加段、堆栈段的段地址在程序中⽤指令填装。

例:
MOV AX,数据段名
MOV DS,AX
MOV AX,附加段名
MOV ES,AX
MOV AX,堆栈段名
MOV SS,AX
LEA SP,栈底
四、过程
1.过程定义
过程名 PROC [NEAR|FAR]
……
……
过程名 ENDP
过程定义在代码段中,过程中必须有返回指令RET。

2.过程调⽤
CALL 过程名
五、宏
1.宏定义
宏名 MACRO [形参表]
……
……
ENDM
如果在宏中使⽤标号,必须先⽤LOCAL语句加以说明。

格式为:LOCAL 标号1,标号2,……
宏定义的位置处于段定义之前。

2.宏调⽤
宏名 [实参表]
如果定义时有形式参数,调⽤时必须有实际参数。

六、源程序结束语句
END 标号
该语句处于源程序的最后⼀⾏,标号为代码段中第⼀指令性语句的标号,该语句必须有标号,⼀般⽤GO或BEGIN或START 等。

§4.4 指令语句
指令性语句是能被CPU执⾏的语句,每条语句编译后都能产⽣⼀个机器代码。

⼀、指令助记符
第3章所讲的每⼀条指令都有⼀个助记符,除了这些指令以外,8086的指令系统还有⼀些附加指令。

1.空操作指令NOP
2.保留空格指令NIL
⼆、指令前缀
LOCK
REP
REPE|REPZ
REPNE|REPNZ
三、操作数寻址⽅式
Pg115
四、串操作指令
Pg116
例:未组合BCD加法程序设计
设 x1 DB ‘1752’
x2 DB ‘3814’
y DB 5 DUP(0)
编程实现:y←x1+x2
按照⼈的读数习惯将x1理解成1752,
x2理解成3814,从低位开始作加法运算。

编程算法如右图所⽰。

§4.5 汇编语⾔程序设计及举例
⼀、顺序程序设计
顺序程序是指没有分⽀、没有循环的直线运⾏程序。

例4-1 两个32位⽆符号乘法程序
Pg120
⼆、分⽀程序设计
分⽀程序是指可以根据某种条件来选择程序的执⾏过程。

例:编程实现
1 当x>0
Y= 0 当x=0
-1 当x<0
三、循环程序设计
循环程序是指可以反复执⾏某⼀部分的程序,将这种结构称为循环结构,⼀个循环结构通常由三部分组成。

(1)循环体
程序中重执⾏的部分。

(2)循环结束条件
任何⼀个循环程序都应有⼀个结构条件,并且这个条件总能满⾜,否则就会构成死循环。

循环的结束分为两种情况:
①已知循环总⼈数;
②循环次数未知,但知道循环结束条件。

(3)循环初态
循环开始前的初始状态,⼀般⽤来设置循环次数,循环的初始地址指针,计数器清零等。

例4-2 Pg122。

四、字符串处理程序设计
计算机经常要处理字符,常⽤的字符编码是ASCII码。

在使⽤ASCII码字符时,要注意以下⼏点:
(1) ASCII码的数字和字符形成⼀个有序序列。

例如数字0~9的ASCII码为30H~39H,⼤写字母 A~Z的ASCII码为41H~5AH 等。

(2) 计算机并不区分可打印的和不可打印的字符,只有I/O装置(例如显⽰器、打印机)才加以区分。

(3) ⼀个I/O装置只按ASCII码处理数据。

例如要打印数码7,必须向它送7的ASCII 码37H,⽽不是响铃符07H。

若按数字键9,键盘送⾄主机的是9的ASCII码39H。

(4) 许多ASCII装置(例如键盘、显⽰器、打印机等)并不⽤整个ASCII字符集。

例如,有的忽略了许多控制字符和⼩写字母。

(5) 不同的设备对ASCII控制字符的解释往往不同,在使⽤中需要注意。

(6) ⼀些⼴泛使⽤的控制字符为:
0AH 换⾏(LF)
0DH回车(CR)
08H退格
7BH删除字符(DEL)
(7) 基本ASCII字符集的编码为7位,在微型计算机中就⽤⼀个字节(最⾼位为零)来表⽰。

例4-3 Pg124。

例4-4 Pg126。

五、ASCII码转换程序设计
输⼊输出设备以ASCII码表⽰字符,数通常是⽤⼗进制数来表⽰,⽽机器内部以⼆进制表⽰。

所以,在CPU与I/O设备之间必须要进⾏码的转换。

实现码转换的⽅法有:
(1) 对于有些转换,利⽤CPU的算术和逻辑运算指令很容易实现,故可⽤软件实现转换;
(2) 某些更为复杂的转换,可以⽤查表来实现,但要求占⽤较⼤的内存空间;
(3) 对于某些转换,⽤硬件也是容易实现的,如BCD到七段显⽰之间转换的译码器等。

例4-5 Pg127。

例4-6 Pg129。

六、有关I/O的DOS功能调⽤
为了在程序运⾏过程中了解运⾏的情况,应该设法把结果在显⽰器CRT上显⽰出来。

要在程序中显⽰结果,⽅便的⽅法是调⽤操作系统中的I/O⼦程序。

操作系统的核⼼是由许多有关I/O驱动、磁盘读写以及⽂件管理等⼦程序构成。

这些⼦程序都编了号,可由汇编语⾔的源程序调⽤。

在调⽤时,把⼦程序的号(或称系统功能调⽤号)送⾄AH,把⼦程序规定的⼊⼝参数,送⾄指定的寄存器,然后由中断指令INT 21H来实现调⽤。

在这⾥通过⼏个程序例⼦介绍少量的有关I/O的功能调⽤,便于读者在程序中使⽤。

1.单字符的接收
2.字符串的接收
3.单字符的显⽰
4.字符串的显⽰
5.⽂件夹操作
6.⽂件操作
7.光标操作
8.图形操作
9.时间操作
10、中断操作
七、宏汇编与条件汇编
在前⾯举例中,若⼀个程序段要多次使⽤,为了简化程序采⽤了⼦程序的办法。

因此,常常把⼀些经常使⽤的典型的程序编为⼦程序,⼀⽅⾯简化了程序的编制,另外也可以提⾼程序的质量和可靠性。

这样的⽬的也可以⽤宏指令和宏汇编来实现。

1.宏指令的⽤途
(1)在汇编语⾔的源程序中,若有的程序段要多次使⽤,为了使在源程序中不重复书写这个程序段,可以⽤⼀条宏指令来代替。

由宏汇编程序在汇编时产⽣所需要的代码。

(2) 宏定义不但能使源程序的书写简洁,⽽且由于宏指令具有接收参量的能⼒,所以功能就更灵活。

(3) 形式参量不仅可出现在操作数部分,也可以出现在操作码部分。

2.IBM宏汇编中主要宏操作伪指令
(1) MACRO
其⼀般格式为:宏定义名是⼀个宏定义调⽤的依据,也是不同宏定义相区别的标志,是必须要有的。

对于宏定义名的规定与对标识符的规定是⼀致的。

宏定义中的形式参量表是任选的,可以没有形式参量,也可以有若⼲个形式参量。

若有⼀个以上的形式参量时,它们之间必须⽤逗号分隔。

对形式参量的规定与对标识符的规定是⼀致的,形式参量的个数没有限制,只要⼀⾏限制在132个字符以内就⾏。

在调⽤时的实在参量多于1个时,也要⽤逗号分隔,它们与形式参量在位置上⼀⼀对应。

但IBM宏汇编并不要求它们在数量上必须⼀致。

若调⽤时的实在参量多于形式参量,则多余的部分被忽略;若实在参量少于形式参量,则多余的形式参量变为NULL(空)。

MACRO必须与ENDM成对出现。

(2) PURGE
⼀个宏定义名,可以⽤伪指令PURGE来取消,然后就可以重新定义。

PURGE伪指令的格式为:
PURGE 宏定义名[,…]
即⼀个PURGE可以取消多个宏定义。

(3) LOCAL
宏定义体内允许使⽤标号。

例如,在AL中有1位⼗六进制数码要转换为ASCII码,则可以⽤以下宏定义:
CHANGE MACRO
CMP AL,10
JL ADD_0
ADD AL,′A′-′0′-10
ADD_0:ADD AL,′0′
ENDM
若在⼀个程序中多次使⽤这条宏指令,则在汇编展开时,标号ADD_0就会出现重复定义的错误,这是不允许的。

为此系统提供了LOCAL伪指令,其格式为: LOCAL 形式参量表
汇编程序对LOCAL伪操作中的形式参量表中的每⼀个形式参量建⽴⼀个符号(⽤??0000~?? FFFF表⽰)以代替在展开中存在的每个形式参量符号。

但是要注意,LOCAL伪操作只能⽤在宏定义体内,⽽且必须是MACRO伪操作后的第⼀个语句,在MACRO 与LOCAL之间不允许有注释和分号标志。

(4) REPT
其⼀般格式为:
REPT 〈表达式〉
{……}指令体
ENDM
这个伪指令可以重复执⾏在它的指令体部分所包含的语句。

重复执⾏的次数,由表达式的值所决定。

例如:把1~10分配给⼗个连续的存储单元。

X = 0
REPT 10
X = X+1
DB X
ENDM
利⽤这个伪指令可以对某个存储区赋值(建⽴⼀个表)。

(5) IRP
其⼀般格式为:
IRP 形式参量(参数表)
{……}指令体
ENDM
此伪指令能重复执⾏指令体部分所包含的语句,重复的次数由参数表中参数的个数所决定(参数表中的参数必须⽤两个尖括号括起来,参数间⽤逗号分隔)。

⽽且每重复⼀次按次序⽤参数表中的参数代替形式参量。

例如:
IRP X〈1,2,3,4,5,6,7,8,9,10〉
DB X
ENDM
因为参数表中的参数是10个,故指令体部分重复执⾏10次。

上例中指令体部分只有⼀条伪指令DB X,其中X为形式参量,在
第⼀次执⾏时,⽤参数表中的第⼀个参数1,代替形式参量则为DB 1;第⼆次执⾏时,⽤参数表中的第⼆个参数2代替形式参量就为DB 2;……所以上例也是把1到10分配给10个连续的存储单元。

(6) IRPC
其⼀般格式为:
IRPC 形式参量,字符串(或〈字符串〉)
{……}指令体
ENDM
此伪指令也能重复执⾏指令体部分所包含的语句。

重复执⾏的次数,取决于字符串中字符的个数。

⽽且每次重复执⾏时,依次把字符串中的字符代替形式参量。

所以,IRPC伪指令与IRP伪指令很类似,只是⽤字符串(此字符串可以包括在两个尖括号中,也可以不包括)代替了IRP指令中的参数表。

3.宏定义嵌套
宏定义允许嵌套,即可以在⼀个宏定义中利⽤宏调⽤,条件是这个宏调⽤必须先定义。

例如:
DIF MACRO N1,N2
MOV AX,N1
SUB AX,N2
ENDM
DIFSQR MACRO N1,N2,RESULT
PUSH DX
PUSH AX
DIF N1,N2
IMUL AX
MOV RESULT,AX
POP AX
POP DX
ENDM
宏定义中还可以包含宏定义,当然在调⽤内层宏定义前必须先调⽤外层宏定义(实质上此调⽤起对内层宏指令的定义作⽤)。

例如:
DIFMALOT MACRO OPNA,OPRAT
OPNA MACRO X,Y,Z
PUSH AX
MOV AX,X
OPRAT AX,Y
MOV Z,AX
POP AX
ENDM
ENDM
其中,OPNA是内层宏定义的名,它也是外层宏定义的形式参数,当调⽤外层宏定义DIFMALOT时,就形成了对内层的定义。

若有宏调⽤:
DIFMALOT ADDITION,ADD
经汇编展开为:
LOGICAND MACRO X,Y,Z
PUSH AX
MOV Z,AX
ADD AX,Y
MOV Z,AX
POP AX
ENDM
4.宏指令与⼦程序的区别
宏指令是⽤⼀条宏指令来代替⼀段程序,以简化源程序。

⼦程序也有类似的功能,那么,这两者之间有什么区别呢?
(1) 宏指令是为了简化源程序的书写,在汇编时,汇编程序处理宏指令,把宏定义体插⼊到宏调⽤处。

所以,宏指令并没有简化⽬标程序。

有多少次宏调⽤,在⽬标程序中仍需要有同样多次的⽬标代码插⼊。

所以,宏指令没有能节省⽬标程序所占的内存单元。

⼦程序是在执⾏时由CPU处理的。

若在⼀个主程序中多次调⽤同⼀个⼦程序,在⽬标程序的代码中,主程序中仍只有调⽤指令的⽬标代码,⼦程序的代码仍是⼀个。

(2)根据上述⽐较,可以看出:若在⼀个源程序中多次调⽤⼀个程序段,则可⽤⼦程序,也可以⽤宏指令来简化源程序。

⽤⼦程序的⽅法,汇编后产⽣的⽬标代码少,也即⽬标程序占⽤的内存空间少,节约了内存空间。

但是,⼦程序在执⾏时,每调⽤⼀次都要先保护断点,通常在程序中还要保护现场;在返回时,先要恢复现场,然后恢复断
点(返回)。

这些操作都额外增加了时间,因⽽执⾏时间长,速度慢。

⽽宏指令恰好相反,它的⽬标程序长,占⽤的内存单元多;但是执⾏时不需要保护断点、保护现场以及恢复、返回等这些额外的操作,因⽽执⾏时间短,速度快。

5.条件汇编
IBM宏汇编提供条件汇编功能。

各种条件汇编语句的⼀般格式为:
IF XX ARGUMENT
(语句体1)
[ELSE] (任选)
(语句体2)
ENDIF
其中,ARGUMENT表⽰条件,其值只有两个:不是真(TURE)就是假(FALSE)。

当条件为真时,汇编程序就对语句体1中所包含的汇编语句进⾏汇编;若条件为假,且语句中如果有ELSE以及语句体2的话,则汇编程序就跳过语句体1⽽对语句体2中的语句进⾏汇编;但若条件为假,且语句中没有ELSE以及语句体2,则汇编程序就跳过这⼀组条件汇编语句,往下进⾏。

ENDIF是任⼀种条件语句的结束符。

IBM宏汇编提供了如下的条件汇编语句:
(1) IF〈表达式〉
若表达式的值不为0,条件为真。

(2) IFE〈表达式〉
若表达式的值为0,条件为真。

(3) IF1
若汇编程序正处在对源程序的第⼀遍扫描的过程中,条件为真。

(4) IF2
若汇编程序正处在对源程序的第⼆遍扫描的过程中,条件为真。

(5) IFDEF〈符号〉
若指定的符号已被定义,则条件为真。

(6) IFNDEF〈符号〉
若指定的符号未被定义,则条件为真。

(7) IFB〈参量〉
若参量为空格,则条件为真。

(8) IFNB〈参量〉
若参量不是空格,则条件为真。

(9) IFIDN〈参量1×参量2〉
若参量1中的串与参量2中的串相同,则条件为真。

(10) IFDIF〈参量1×参量2〉
若参量1和参量2的串不同,则条件为真。

相关文档
最新文档