第一章:计算机概述及基础知识
一、计算机中常用的半导体存储器类型和缩写:
1、只读存储器ROM:(Read Only Memory)
2、一次性可编程只读存储器 PROM(Programmable ROM)
3、随机存取存储器:RAM(Random Access Memory)
4、静态RAM:SRAM(Static RAM)
5、动态RAM:DRAM(Dyanmic RAM)
6、光可擦除电可编程只读存储器 EPROM(Erasable Programmable ROM)
7、电擦除电可编程只读存储器 EEPROM(Electrically Erasable
Programmable ROM)
8、闪烁存储器 Flash Memory
二、常用存储器容量单位及表示方法:
1字节=8位二进制数,
1字=2字节=16位二进制数,双字=4字节=32位二进制数
1KB=1024B(字节) 1MB=1024KB
1GB=1024MB 1TB=1024GB
1节=16字节 1页=256字节 1段=64KB(字节)
三、存储器中常用的术语、概念和含义:
1、存储器的物理地址:使用CPU全部地址线对存储器进行的编址,称为
存储器的物理地址或绝对地址。(使用CPU全部寻址范围内的地址码对存储单元进行的编址称为存储器的物理地址或绝对地址。)
2、存储器的逻辑地址:由CPU内部段寄存器(即段基址)和偏移地址寄存
器(例如:SI、DI、BP、和SP等寄存器)的当前值所构成的地址称为逻
辑地址。
3、一个存储单元的物理(绝对)地址是唯一的,但可以有多个逻辑地址!
(或:一个存储单元可以有多个逻辑地址,但仅有一个物理地址!)
存储单元的物理地址可由段寄存器(即段基址)和偏移地址经运算或变换得到。其算法为:绝对地址=段基址X16(左移4位)+偏移地址
例1:段基址存放在段寄存器CS中,即CS=2000H,偏移地址在IP中,即IP=2200H,
则:绝对地址=段基址X16+偏移地址=20000H+2200H=22200H
例2:已知:CS=2200H IP=0200H,试计算其绝对地址。
绝对地址=段基址X16+偏移地址=22000H+0200H=22200H
由上可知绝对地址为22200H的存储单元它的逻辑地址可以有多个。
四、关于计算机中断技术中的基本概念和技术术语:
1、中断定义:计算机在执行当前程序或任务时,由于随机或突发事件的
产生而暂停当前的工作转去为其服务,服务完成后再返回到刚才的断点处继续在这之前的工作,此过程称之为:中断。
2、断点:CPU响应中断时程序中止处的CS和IP的值(即:程序中止处的
下一条指令的地址)。
3、中断源:采用中断方式与CPU或系统进行信息交换的外设或部件。
4、中断向量:中断服务子程序的入口地址被称之为:中断向量。
5、中断向量表:用来存放中断服务子程序的入口地址的存储区域被称之
为:中断向量表。
6、中断类型码:在CPU响应外设中断请求时,由外设向CPU提供的用来
查找中断向量表的索引码。
7、现场:在中断服务子程序中所使用的那些与主程序中符号相同但定义
或作用不同的全局变量、工作寄存器或工作单元等。(即:在执行中断服务子程序时需要保护的内容)
8、中断优先级:外设产生中断请求时CPU或中断控制器对其进行响应或
处理的先后顺序。
9、可屏蔽中断:可使用中断开、关指令控制CPU对中断请求的响应。这
类中断称之为可屏蔽中断。8086 CPU的开中断指令为STI,可允许CPU响应外部中断请求。关中断指令为CLI可禁止CPU响应外部中断请求。
10、非屏蔽中断:CPU的中断响应不能使用中断开、关指令进行控制。这
类中断称为不可屏蔽中断或非屏蔽中断(不可使用中断开、关指令控制CPU对中断请求的响应。这类中断称之为不可屏蔽中断或非屏蔽中断)。非屏蔽中断的优先级要高于可屏蔽中断。
11、中断优先级:多个中断源同时申请中断时CPU的响应策略或中断嵌套
规则。
12、采用中断技术的优点:CPU工作效率高、实时性好、便于处理随机和
突发事件。
13、中断响应和处理的实质内容:确定发出中断请求的中断源(即外设)
或随机事件,找到并执行为该中断源服务的中断服务子程序。也即:其 实质就是为了执行一段服务程序。
五、8086/8088CPU的中断系统
1、中断分类:硬件中断、软件中断和内部操中断。
a. 硬件中断:由外设或外部信号所产生的中断请求称之为:硬件中断。
其硬件中断又可分为非屏蔽中断和可屏蔽中断,其中,非屏蔽中断
请求信号要连接到CPU的NMI引脚,而可屏蔽中断请求信号要连接到CPU的INTR引脚.
b. 软件中断:由执行CPU中断指令:INT n所产生的中断称为软件
中断。
c. 内部操中断:由CPU内部的一些特定操作(例如:除数为0时所引起
的除数为0中断,符号数运算过程中产生溢出时所引起的溢出中断,为方便程序的调试,每执行完一条指令时都可产生一次中断的单步中断等)所引起的中断称之为:内部操作中断。
2、中断响应条件:
a. 非屏蔽中断:将非屏蔽中断源的中断请求信号连接到CPU的NMI引
脚,编写好中断服务子程序,并在主程序的系统初始化程序中建立好中断向量表(即:将中断服务子程序的入口地址填写到中断向量表中,其向量表地址由分配给该外设的中断类型码确定)。
b. 可屏蔽中断:将可屏蔽中断源的中断请求信号连接到CPU的INTR
引脚,编写好中断服务子程序,在主程序的系统初始化程序中建立好中断向量表,并在主程序中的适当位置处使用CPU的开中断指令STI打开CPU中断,允许CPU接收外部可屏蔽中断请求。
c. 软件中断:编写好中断服务子程序,在主程序的系统初始化程序中
建立好中断向量表,在需要中断时的程序位置处放一条INT n指令。
d. 内部操中断:编写好中断服务子程序,在主程序的系统初始化程序中建立好中断向量表。当系统中出现特定内部操作(即:除数为0、溢出和单步操作)时即可对其进行服务。
e.
3、中断向量表的建立:即:利用程序或指令将中断服务子程序的入口地
址(逻辑地址)填写到中断向量表中。中断向量表的地址由外设的中断类型码确定。
例如已知某外设的中断类型码为20H,其中断服务子程序的入口地址
为:1234H:5678H,为其建立中断向量表就是将中断服务子程序的入口
地址1234H:5678H填写到自内存空间地址0段20HX4开始的连续4个字
节的存储单元中,即0000H:20HX4+0---0000H:20HX4+3的连续4个单元
中,其存放顺序为:低地址存放低字节,高地址存放高字节:即自20HX4
开始的连续4个字节的存储单元的内容分别如下:
(20H*4+3)=12H。
(20H*4+2)=34H,
(20H*4+1)=56H,
(20H*4+0)=78H,
4、可屏蔽中断的响应过程:
(1). 从数据总线D.B上读取外设提供的中断类型码并暂存.
(2). 将FR内容存入堆栈保护.
(3). 将标志位IF和TF清0,以便禁止INTR中断.
(4). 将当前的程序断点CS:IP存入堆栈保护.
(5). 利用外设提供的中断类型码计算中断向量表地址,并从中取出中
断处理子程序的入口地址转去执行服务程序.
(6). 执行完中断服务子程序后恢复断点和FR的内容.
(7). 从中断返回。(即执行一条中断返回指令IRET)
第5章86系列微型计算机的指令系统
一、 寻址方式:如何获得操作数的方法称之为寻址方式,8086CPU的寻址方式有以下4类:
1、 立即寻址:当操作数直接出现在指令中时称为立即(数)寻址
2、 寄存器寻址:当操作数在CPU内部寄存器中时称为寄存器寻址
3、 直接寻址:当操作数的地址出现在指令中时称为直接寻址
4、 寄存器间接寻址:当操作数的地址出现在寄存器中时称为寄存器寻址。在该寻址方式中操作数一定在存储单元中,但存储单元的有效地址要求使用寄存器指定,这些寄存器可以使用BX、BP、SI和DI之一,即:存储单元的有效地址要放在这其中的某个寄存器中。
有效地址:寻址所需要的偏移地址称之为有效地址
注意:在以上寻址方式中若目标操作数是非CS的段寄存器时,只能采用寄存器寻址方式产生或获得操作数!
例如:将数据段寄存器DS的内容设置为2000H
若直接使用指令:MOV DS,2000H是错误的,可改为以下方式:
MOV AX, 2000H
MOV DS, AX
注意:两个无符号数相比较时,仅用CF标志即可判断两数大小,若CF=0则被减数大于等于减数。两个带符号数相比较时, 若OF和SF状态值相同则说明被减数大于等于减数,否则说明被减数小于减数。因两个相同符号数比较时不会发生溢出!
例1:将AX内容加1:即AX+1---AX
可以使用指令:ADD AX, 1 ;该指令的寻址方式为立即数寻址,具体操作和指令执行时间见P444第6栏中的第6行:acc, imm
即:ADD acc, imm;其中acc为累加器AX,imm表示立即数,该指令的时钟周期数为4,字节数为2—3。而如果改用:INC AX 指令也可实现AX+1;但其指令的时钟周期数为2,字节数仅为1,见P447第25栏中第1行:reg16(因AX为16位,如果使用INC AL时为8位操作,即为reg8)。尽管以上2条指令的操作功能相同,但指令执行后对状态标志寄存器的影响是不一样的!ADD指令能影响除控制标志之外的所有的状态标志:CF、PF、AF、ZF、SF、OF,但INC指令不影响CF标志!
即:若AL=0FFH时,执行INC AL后CF的状态不变!
例2:将AX内容清0
可以使用指令:MOV AX, 0 ;该指令的寻址方式为立即数寻址,具体操作和指令执行时间见P450第40栏中第6行:reg, imm,即:MOV reg, imm,由表中可知该指令的时钟周期数为4,字节数为2—3。
但如果改用:XOR AX, AX 指令,同样也可实现对AX清0的目的,但其指令的时钟周期数为3,字节数为2,见P455第75栏中的第1行:reg,reg,即:XOR reg, reg.
第6章微型计算机的程序设计
例3:编一段程序完成符号函数。见P151习题6.5,答案见P471
……………………………………………
XDB?;定义自变量DATA1
YDB0;定义函数值存放单元DATA2
………………………………………………
MOVAL,X;取自变量送AL以便对其进行判断
CMPAL,0;影响所有标志位:ZF、SF、CF等标志位
JNZPNZ;X不为0转移
MOVAL,0;X=0
MOVY,AL;将0送函数值存放单元中
HLT
PNZ:JSPS; 测试符号标志位若X<0转移。见P133转移指令表
MOVAL,1;X>0
MOVY,AL;将1送函数值存放单元中
HLT
PS:MOVAL,0FFH;X<0,送-1的补码
MOVY,AL;将0送函数值存放单元中
HLT
P138 6.2 简单程序
例6.1 将自10050H起连续存放的两个16位数求和后存入其后。低字节在低地址
例6.1 程序1
MOV AX, 1000H ;建立数据段指针
MOV DS, AX
MOV SI, 50H ;建立被加数偏移地址指针
MOV DI, 52H ;建立加数偏移地址指针
MOV BX, 54H ;建立和偏移地址指针
CLC ;清进位位。该指令可省,因下一条指令XOR AX, AX能够影响标志!!!
XOR AX, AX ;累加器清0
MOV AX, [SI] ;取出被加数送AX
ADC AX, [DI] ;两数相加
MOV [BX], AX ;存结果
HLT ;暂停
例6.1 程序2
MOV AX, 1000H ;建立数据段指针
MOV DS, AX
MOV SI, 50H ;建立被加数偏移地址指针
MOV AX, [SI] ;取出被加数送AX
ADDAX,[SI+2];两数相加,注:仅2个数相加时可以不使用带进位加法指令!
MOV [SI+4], AX ;存结果
HLT ;暂停
例6.2将10050H单元的内容拆为两段,每段4位,存入其后
MOV AX, 1000H ;建立数据段指针
MOV DS, AX
MOV SI, 50H ;建立被加数偏移地址指针
MOV AL, [SI] ;取出待拆分数据送AL
AND AL, 0FH ;屏蔽高4位,分离出低4位
MOV [SX+1], AL ;存低4位
MOV AL, [SI] ;再次取出待拆分数据送AL
MOV CL, 4 ;建立逻辑右移次数计数器
SHR AL, CL ;逻辑右移4位分离出高4位
MOV [SI+2], AL ;存高4位
HLT
P1406.3分支程序
例6.3 计算AX-BX的绝对值
例6.3 程序1P141程序有错
CLC ;该指令可省
SUB AX, BX ;应改用CMP比较指令
JC AA
MOV DI, 2800H ;建立数据指针
MOV [DI], AX ;存结果
HLT
AA: SUB BX, AX ;由于前面执行SUB指令时操作数AX已被破坏。或改
; 为:NEG AX
MOV DI, 2800H ;因此得不到正确结果
MOV [DI], BX ; MOV[DI],AX
HLT
例6.3 程序2
MOV DI, 2800H ;建立数据指针
CMPAX,BX;两数比较
JC AA ;若AX小于BX则转AA
SUB AX, BX ;计算两数之差
MOV [DI], AX ;存结果
HLT
AA: SUB BX, AX
MOV [DI], BX
HLT
例6.3 程序3
MOV DI, 2800H ;建立数据指针
SUB AX, BX ;两数相减
JC AA ;若AX小于BX则转AA
SUB AX, BX ;计算两数之差
MOV [DI], AX ;存结果
HLT
AA: NEGAX
MOV[DI],AX
HLT
例6.4 从71H外设输入一个数据M,若M小于10则向73H外设输出00H,若M大于20则向73H外设输出0FFH,否则向73H外设输出88H。
START:IN AL, 71H ;从71H外设读入数据
CLC ;该指令可省,因下一条指令CMP AL,10能够影响标志!!!
CMP AL, 10 ;判断是否小于10
JC LP1 ;若小于10则转LP1
CMP AL, 20 ;判断是否小于20
JC LP2 ;若小于20则转LP2
MOV BL, 0FFH ;建立M大于20时的输出数据
LP3: OUT 73H, BL ;将数据输出到73H外设
HLT
LP1: MOV BL, 0H ;建立M小于10时的输出数据
JMP LP3
LP2: MOV BL, 88H ;建立中间输出数据
JMP LP3
P143 6.4循环程序
例6.5 求两个8字节数之和,两数自10050H起连续存放,并将求和结果存入其后。
程序1见P144下面
程序2按字(16位)求和
START:MOV AX, 1000H ;建立数据段指针
MOV DS, AX
MOV SI, 50H ;建立被加数偏移地址指针
MOV CX, 4 ;建立计数器
CLC ;清进位位
NEXT: MOV AX, [SI] ;取出第一个数据的低字数据送AX
ADC AX, [SI+8] ;与第2个数据的低字相加
MOV [SI+16], AX ;存结果
INC SI ;调整数据指针
INC SI ;调整数据指针
DEC CX ;计数器减1
JNZ NEXT ;未完继续下一个字的相加
HLT
说明:如果使用CX做为计数器时可将上面的两条指令DEC CX 和JNZ NEXT简化为一条指令:LOOPNEXT见P133转移类指令表倒数第2栏“循环控制”指令中的
LOOP 目标标号
程序3按字节(8位)求和
START:MOV AX, 1000H ;建立数据段指针
MOV DS, AX
MOV SI, 50H ;建立被加数偏移地址指针
MOV CX, 8 ;建立计数器
CLC ;清进位位
NEXT: MOV AL, [SI] ;取出第一个数据的低字节数据送AX
ADC AL, [SI+8] ;与第2个数据的低字节相加
MOV [SI+16], AL ;存结果
INC SI ;调整数据指针
LOOP NEXT ;未完继续下一个字节的相加
HLT
P145
例6.6 设计一个软件延时程序,延时时间约1mS左右
分析:当延时时间不长且计时精度要求不高时,可利用指令的执行时间实现延时,例如:当CPU主频为8MHZ时,其时钟周期为0.125uS,如果知道了指令所需要的时钟周期数便可知道指令的执行时间。于是可利用循环程序实现软件延时。
即:循环次数X=所需延时时间/一次循环时间,若循环体中采用PUSHF和POPF进行延时,而循环控制指令采用LOOP时,从P443附录A的指令表中可查到PUSHF指令的时钟周期数是14个(见P452第51栏右数第2列),而POPF指令的时钟周期数是12个(见P451第49栏右数第2列),而LOOP指令的时钟周期数是17/5个(见P449第37栏右数第2列),即跳转时(CX-1不等于0)为17个时钟周期,后继时为5个时钟周期。于是:循环次数 N=1000/[(14+12+17)0.125]≈186
START: MOV CX, 186 ;设置循环次数
LP1: PUSHF ;循环体
POPF ;循环体
LOOP LP1 ;未完继续
HLT
写成更为通用的一般的延时子程序形式如下:
DT: MOV CX, N ;设置循环次数,或者将CX作为入口参数
DT1: NOP ;循环体
NOP ;循环体
DEC CX
JNZ DT1 ;未完继续
RET
循环体中也可使用其它指令,例如NOP(该指令为3个时钟周期,见P451右数第2栏)等,但循环次数要重新计算!如果需要再增加延时时间,则可采用双循环程序见P146,还可增加循环体中的指令条数,例如再增加几对PUSHF和POPF指令,或在循环体中使用周期数更多的指令,例如乘除法指令等,乘法指令MUL见P450中的42栏,周期数最少的8位数乘法MUL reg8也要70-77个时钟周期,而16位数乘法MUL reg16则要118-133个时钟周期,若使用MUL mem16则至少要128个时钟周期。
所有转移指令都在P448 29栏中时钟周期都为16/4
P146 6.5子程序
例6.8有2个数据块分别自2000H和2800H起存放,每个数据块的第1个单元分别为数据块长度,其后是数据内容(类型为字节),试编一个程序分别找出各数据块中的最大值,分别存入MAX1和MAX2.。
START:: MOV SI, 2000H ;建立数据块1指针指向数据长度单元
MOV CL, [SI] ;取出数据长度
MOV CH, 0 ;构成16位计数器
DEC CX ;调整计数器
INC SI ;调整数据指针指向数据
CALL F_MAX ;调用找最大值子程序,入口参数为SI,CX
MOV MAX1, AL ;出口参数AL为最大值存入指定单元
MOV SI, 2800H ;建立数据块2指针指向数据长度单元
MOV CL, [SI] ;取出数据长度
MOV CH, 0 ;构成16位计数器
DEC CX ;调整计数器
INC SI ;调整数据指针指向数据
CALL F_MAX ;调用找最大值子程序,入口参数为SI,CX
MOV MAX2, AL ;出口参数为AL中存放着最大值
HLT ;存入指定单元
;找最大值子程序,人口参数为SI:数据指针;CX:计数器
出口参数为AL:用来存放找到的最大值
F_MAX:
MOV AL, [SI]
NEXT: INC SI
CMP AL, [SI]
JNC NEXT1
MOV AL, [SI]
NEXT1 LOOP NEXT
RET
练习题:将自DATA起连续存放的2个单元的字节数据分离(高4位为0,低4位为数据)后送D_BUF开始的连续单元中。
习题:P1074.1—4.14P135 5.1—5.9P1516.1—6.7
第七章 微型计算机汇编语言及汇编程序
关于汇编语言的基本概念和术语
1、 汇编语言:面向机器的利用助记符、符号地址、变量和标号等编写程序的语言称为汇编语言。(或简称为:面向机器的编程语言)
2、 源程序:用汇编语言编写的程序称为源程序。
3、 汇编:由于用汇编语言编写的程序机器(即CPU)不能够直接执行,必须翻译成机器代码(即二进制代码)组成的目标程序,这个翻译过程称为汇编。(由于机器不能够直接执行用汇编语言编写的程序,只能执行由机器代码(即二进制代码)组成的目标程序,这个将汇编语言翻译成机器代码的过程称为汇编。)
4、 汇编程序:完成上述翻译过程的软件称为汇编程序。
例如而空操作指令NOP的机器码为90H(见P451第44栏),暂停指令HLT的机器码为0F4H(见P447第21栏),汇编程序在汇编时即将NOP和HLT指令分别翻译成机器码90H和0F4H后分别存入程序段存储器中后CPU才能执行。
5、 反汇编:将机器代码转换成汇编语言的过程称为反汇编。
6、 机器码:CPU可以直接执行的代码称为机器码或目标程序。
7.1宏汇编语言的基本语法
一、常数、变量和标号
汇编语言程序语句=执行性语句+非执行性语句(即说明性语句)
执行语句:由CPU或处理器指令组成。与CPU类型有关,执行后CPU
都会产生相应的操作。
非执行语句或说明性语句:由伪指令或宏指令组成。与CPU类型无关,
不产生CPU的任何操作,只与汇编程序有关,不同版本的汇编程序
支持不同的伪指令
伪指令语句格式(见P154图7-2)与执行指令的语句格式(见P109图5-1)基本相同,但其伪指令语句和执行指令语句的作用大不不同,在汇编时伪指令语句不产生机器码。仅用来告诉汇编程序如何将指令语句或伪指令语句中的操作数转换成目标代码。
1、 CPU或处理器指令中的操作数可以是立即数、寄存器和存储单元。且立即数只能是整数。
2、 执行性语句中的标号后要加冒号‘:’,而非执行性语句的标号后不能加冒号!
3、 伪指令中的操作数可以是常数、字符串、常量名、变量名、标号、表达式和专用符号(例如:BYTE、WORD、FAR、PARA)等,可以有多个,各参数之间用逗号分隔。
l 常数:二、八、十、十六进制数,实数、带引号的字符串(例如“AB”=41H、42H)等。
l 标号:指令目标代码的符号地址。常用作转移指令或子程序调用指令中的目的操作数。
l 变量:存放在内存单元中的数据或称内存数据(即对内存数据起一个名,常被称作存储单元的符号地址)。这些数据在程序运行期间可被随时访问或修改。其属性有3个:
段属性SEG:指出该变量所在的逻辑段。
偏移属性OFFSET:指出该变量所在逻辑段中相对该段起始点的偏
移量。
类型属性TYPE:表示该变量所占用内存单元的字节数。一般由数
据定义伪指令进行定义,常用数据定义伪指令有:
DB:定义字节。见P160伪指令中的:2.内存数据定义伪指令
DW:定义字。
DD:定义双字。
变量在使用前必须要先进行定义:即对其进行命名、定义类型和预置初值
变量定义伪指令的语句格式为:见P156
变量名 变量类型 表达式1,表达式2,…
其表达式形式如下:
1、数值表达式:数或简单算术表达式。例如
DATA1DB50H,50
DATA2DB01,12,23,23+5×6
DATA3DW1234H,2345H,3456H,56X78/28
2、?表达式:不带引号的?表示该内存单元可为任意值
DATA1DB?,?;自DATA1地址开始预留2个单元
DATA2DB1,2,3,?,?;前3个字节单元置初值,后2个
;字节单元随意
DATA3DW?,?,3456H,56X78/28 ;前2个字单元随意,
;后2个字单元预置初值
3、字符串表达式:字符串必须用单引号括起来且不超过256个字符,
存放时按字符串的书写顺序自左向右按地址递增顺序存放。
数据类型为DB时,每个字符分配一个字节单元。
数据类型为DW时,每2个字符为一组分配2个字节单元,前一
字符在高地址字节,后一字符在低地址字节,每个数据项不能多于2个字符。
数据类型为DD时,每2个字符为一组分配4个字节单元,将字
符存入低2个字节顺序同DW,高2个字节存入00H.
例1:STRING1 DB ‘ABCDEF’;即将41H-46H存入自STRING1开始的连续
6个字节单元中
例2:STRING2 DW ‘AB’,‘CD’,‘EF’;即将41H-46H存入自STRING1
[STRING2]=42H ; 开始的连续3个字单元中
[STRING2+1]=41H ;
[STRING2+2]=44H
[STRING2+3]=43H
[STRING2+4]=46H
[STRING2+5]=45H ; 见P157图7-3
4、带DUP的表达式:用于对多个内存单元进行重复设置。也称重复数据
操作符或重复数据操作伪指令。
语句格式为:变量名 变量类型 表达式1DUP(表达式2);其中表
达式1为重复次数,表达式2为重复内容。
例1:DATA1 DB 20HDUP(?);自DATA1地址开始预留20H个
;单元,内容随意。
例2:DATA2 DW 20DUP(0);将自DATA1地址开始的连续20个
;字单元(即40个字节)清0
二、常用表达式和运算符:
1、算术运算符 2、逻辑运算符 3、关系运算符
4、分析运算符:(见P158)
(1)SEG求段基址 ;格式:SEG <符号名>
例:SEG DATA1 ;求变量DATA1的段基址
(2)OFFSET求偏移地址;格式:OFFSET <符号名>
例:OFFSET DATA1 ;求变量DATA1的偏移地址
(3)TYPE求符号名或变量的类型值;格式:TYPE <符号名>;其变
量的类型值见P159表7—1
例如:TYPEDATA1;=1,TYPEDATA2;=2
其中DATA1、DATA2的类型定义见上面例1、例2
5、组合运算符:
(1)定义符号名为新类型;格式:<类型> PTR<符号名>
例1:MOV AX,WORD PTR DATA1 ;将DATA1重新定义为字类型
例2:MOV AL,BYTE PTR DATA2 ;将DATA1重新定义为字节类型
7.2常用伪指令见P160
1、符号定义伪指令作用:对所用符号进行赋值
格式:<符号名>EQU<表达式>;定义后不能重新赋值
<符号名>=<表达式>;定义后可以重新赋值
2、内存数据(即变量)定义伪指令:即:DB、DW、DD
作用:定义内存变量的类型属性
[变量名]DB<表达式>
3、段定义伪指令作用:对段进行命名和定位
格式:<段名>SEGMENT[定位方式] [连接方式] [‘类别名’]
编程时一般使用默认值(即段边界方式)即可。
定位方式是指段的起始地址常用的定位方式(见P162)如下:
PAGA:页边界,即段起始地址的低8位为0
PARA:段边界,即段起始地址的低4位为0.该方式为系统默认方式
WORD;字边界,即段起始地址的最低位为0
BYTE:任意值
4、段寄存器说明伪指令
格式:ASSUME段寄存器名:段定义名1…
5、过程定义伪指令:
格式:<过程名>PROC[NEAR或FAR];括号内为过程属性
…………
<过程名>ENDP
6、模块开始伪指令:格式:NAME模块名
作用:对程序模块进行命名,模块名可以自行定义,但不能使用关键字!可以默认,其默认名为列表文件标题的前6个字符,若无标题时则默认名为该程序模块的源文件名。
7、模块结束伪指令:格式:END[启动标号或过程名]
作用:通知汇编程序源文件结束,并给出执行程序的入口地址。启动地址只有在主程序模块才有意义。
8、定位伪指令:格式:ORG<表达式>
作用:指定数据或程序在内存中的起始偏移地址,从表达式指定的起点开始连续存放直到遇到新的ORG指令为止。表达式为无符号数。
9、列表伪指令:
(1)建立标题:格式:TITLE标题
作用:为列表文件每页的第1行定义大标题
(2)建立小标题:格式:SUBTTL标题
作用:为列表文件每页定义小标题,输出在大标题之后。
(3)自动排版:格式:PAGE行数,每行字数(即列数)
作用:为列表文件定义每页行数(10—255行)和每行字符数
(60--132),默认值是66行80列。
伪指令或说明性语句的作用:对变量、工作单元或符号等进行定义或说明,以增加程序的可读性等。例如:
已知16位发动机转速测量值存放在2000H和2001H(高8位)单元中,8位温度测量值存放在2002H单元中,试编一个程序将转速测量值送AX寄存器中,温度测量值送DL 寄存器中。
程序1:
MOV AX, [2000H] ;将转速测量值送AX寄存器
MOV DL, [2002H] ;将温度测量值送DL寄存器
分析:尽管程序简单,但不知内存单元中存放的是何数据,缺乏可读性!
程序2:
DATASEGMENT;段定义伪指令
ORG 2000H ;对存放数据的偏移地址进行定位伪指令
ZS DW 0 ;分配转速存放单元
WD DB 0 ;定义温度存放单元
DATAENDS
……………………………………………
MOV AX, ZS ;将转速测量值送AX寄存器
MOV DL, WD ;将温度测量值送DL寄存器
由此可知利用伪指令对工作单元或变量进行了定义后,使得程序具有了可读性!
7.3 宏指令
7.3.1宏指令概述:
为简化汇编语言程序的书写,将程序中重复出现的内容或代码定义为“宏指令”(即用一条宏指令代替),在其原位置处只需放一条宏调用语句即可,于是可大大简化源程序的书写,提高源程序的可读性。宏指令类似于子程序或过程,但二者有明显的区别:
1、执行方式不同:宏调用语句属于说明性语句由汇编程序MASM-86中的宏处理程序代换进行处理,不会引起CPU的任何操作,而子程序调用或过程调用语句是由CPU执行。
2、对内存空间的占用方式不同:宏指令在执行时是由汇编程序将宏指令出现的地方将其原内容或原程序段换回!只简化书写,不节省内存!而子程序或过程是将重复出现的内容或代码与主程序分开单独存放!其目标代码在内存中只保留一份!既简化书写又节省内存!
3、CPU工作时间开销不同:由于宏指令在汇编时是将该宏指令所代替的原内容换回,因此CPU在执行程序时无需额外耗费任何时间,而产生子程序或过程调用时,CPU必须要进行断点甚至现场的保护和恢复,从而产生额外的时间开销,而降低程序的执行速度。
4、对工作参数的要求不同:在进行宏调用时允许改变或修改其工作参数,使得同一条宏指令在各次不同的调用过程中可完成不同的操作,具有较好的灵活性,而子程序或过程一旦被定义,一般不允许修改参数,因此如何子程序或过程在各次调用中只能完成相同的功能。其灵活性不如宏指令!
由上归纳可知:一般情况下当程序中重复性的内容或代码较长,且工作参数相对固定时可采用子程序或过程,当程序中重复性的内容较少或代码较短,且希望在各次调用时能够修改工作参数时,宜采用宏调用方式。
7.3.2宏指令的定义和使用方法
一、宏指令使用说明:
宏指令在使用前必须要先进行定义!其步骤如下:
1、宏定义:即对程序中所出现的重复性内容或代码进行定义,并起一个
名。
2、宏调用:在程序中出现重复性内容或代码位置处用一条宏调用语句进行替换。(即将其重复性内容或代码位置处通过宏指令名来调用它)
3、宏扩展(宏展开):由宏汇编程序在宏调用语句(即宏调用指令)处,将原内容换回。并在展开的指令语句左端加上标识符:+
二、宏代换和宏调用语句格式:
1、宏代换语句格式:
宏名MACRO[形式参数1,形式参数2,…];形式参数为可选项
宏体;即需要进行宏代换的内容或代码
ENDM
2、宏调用语句格式:
宏名实在参数1,实在参数2,…;实在参数必须与形式参数对应
P167例:
宏定义AHMACROY,X;Y、X分别为形式参数
MOVCL,X
RO&YCL;教材P167原题有错,该语句缺少源操作数!
;当被宏代换的内容为指令助记符中的符号
;时,要在符号前加宏代换符 &
ENDM
AH MACRO Y, X;AH为宏名,Y、X为形式参数
MOV CL,X
RO&Y AL,CL;或为:RO&Y CL,CL
ENDM
宏调用:AHR,5; 其中R为和形式参数表中的Y所对应的实在参数
;5为和形式参数表中的X所对应的实在参数
宏展开:+MOVCL,5
+RORAL,CL
补充:宏指令和子程序应用举例:
已知两位LED数码显示器的I/O地址分别是:个位为LED0,十位为LED1,试编一个程序将DATA单元的内容送LED进行显示。即该单元的低4位送个位LED0,高4位送十位LED1。
ORG1000H;程序模块定位
DATASEGMENT;定义数据段
LED_TBL DB 3FH,06H,5BH,……;建立0—9的7段LED数码显示器段码表
DATA DB 36H ;预置待显数据
DATAENDS ;数据段结束
STACSEGMENT PARA STACK‘DAT ’;定义堆栈段
STA1 DW 10 DUP(?)
STACENDS;堆栈段结束
CODE