第2章 指令系统及汇编语言程序设计.docx
《第2章 指令系统及汇编语言程序设计.docx》由会员分享,可在线阅读,更多相关《第2章 指令系统及汇编语言程序设计.docx(104页珍藏版)》请在冰豆网上搜索。
![第2章 指令系统及汇编语言程序设计.docx](https://file1.bdocx.com/fileroot1/2022-11/27/5fb019e5-2433-4bab-9f91-deae10ac2877/5fb019e5-2433-4bab-9f91-deae10ac28771.gif)
第2章指令系统及汇编语言程序设计
第2章指令系统及汇编语言程序设计
§1概述
一、指令系统
人们要求计算机解决计算或处理信息的问题,首先必须把问题要转换为计算机能识别和执行的一步步操作指令,我们把这种要求计算机执行的各种操作用命令形式写下来,这就称为指令。
通常一条指令对应一种基本操作,例如加、减、传送、移位等,一个计算机能执行什么样操作,能做多少种操作,是由该计算机的指令系统所决定的,因此,计算机所能执行的全部指令,就是计算机的指令系统。
微处理器的主要功能是由它的指令系统来体现的。
目前,一般小型或微型计算机的指令系统可以包括几十种或百余种指令(8086有115条)。
每种计算机都有自己固定的指令系统,8086/8088的指令系统和M68000的指令系统具有不同的指令,不能相互兼容,也就是说,8086/8088的指令系统中的指令,只能由8086/8088微处理器所识别和执行,而不能被M68000微处理器所识别和执行。
但8086/8088微处理器可以执行8080/8085指令系统中的指令,所以只有同系列微处理器指令系统是相兼容的。
二、指令格式
计算机中的指令有操作码字段和操作数字段两部分组成。
操作码字段指出计算机所要执行的操作,而操作数字段则指出在指令操作过程中所需的操作数据。
例如,加法指令一方面需要指定做加法操作的部分,即操作码字段。
另一方面需给出被加数和加数部分,即操作数字段。
操作数字段可以是操作数本身,也可以是操作数地址或地址的一部分,还可以是指向操作数地址的指针或其他有关操作数的信息。
指令的格式一般是:
操作码操作数………… 操作数
操作数字段可以有一个、二个或三个,通常称为一地址、二地址或三地址指令。
例如,单操作数指令,它只需指定一个操作数参加操作,如移位指令、增1、减1指令等,这都是一地址指令。
大多数运算指令是双操作指令,如算术和逻辑运算指令,对于这种指令,有的机器采用三地址指令,除指出参加运算的两个操作数以外,还指出运算结果存放地址,现大多数计算机采用二地址指令,此时分别称两个操作数为原操作数和目的操作数。
尽管在指令执行前这两个操作数都是原始操作数,但指令执行后将把运算结果存放到目的操作数的地址中去,当然目的操作数的原始数据将会丢失。
如果此原始数据在以后的运算中还会用到,那么必须在运算之前给它准备一个副本(即预先存储在内存或寄存器中)。
8086/8088的运算指令就采用这种二地址指令。
三、寻址方式
指令中操作数字段实质上指出参加操作运算的操作数存放于何处。
一般说来,操作数可以存放在指令代码中,称为立即数。
操作数也可以存放在CPU的内部寄存器中,称为寄存器操作数。
操作数绝大多数存放在存储器中,称为存储器操作数。
对于一部分I/O指令来说,操作数可以存放在接口电路的寄存器中。
指定立即数和寄存器操作数的表示方法比较简单。
而对存储器操作数来说,一个存储单元的地址就需要20位,怎样设法使它在指令的操作数字段的表示中减少位数呢?
另外,从程序运行时的数据结构来看,操作数常常不是单个的数,往往是成组的以表格或数组形式存放在存储器的某一区域中,在这种情况下,指令用什么方式来指定操作数的地址更好呢?
从程序设计的通用性来看,操作数或操作数存放的地址在指令中的指定应具有易于改变的灵活性,因此,需要有多种方式来指定操作数或操作数地址的问题。
指令中用于说明操作数所在地址的方法,称为寻址方式。
我们知道,计算机只能识别二进制代码,机器指令是由二进制代码组成的,这种指令称为机器码,机器码是由一串0和1组成,没有明显的特征,人们不好记忆,不易理解,易出错。
所以,编制程序成为一种十分困难和繁琐的工作。
因而人们就用一些助记符—通常是指令功能的英文词的缩写来代替操作码。
如8086/8088中,数的传送指令用助记符MOV(MOVE缩写)表示。
例:
MOVDS,AX机器码:
8ED8。
MOVBP,SP机器码:
8BEC。
MOVAX,ES:
[BX]机器码:
268B07
这样,每条指令有明显的特征,易于理解和记忆,也不易出错,此即汇编语言阶段。
汇编语言书写的指令操作码用助记符代替,操作数也可用符号或符号地址(称为标号)来表示,它与机器指令是一一对应的。
本章均用汇编语言格式书写指令。
四、指令的执行时间
一条指令的执行时间是取指令、取操作数、执行指令及传送结果各个阶段所需时间的总和。
详细讨论各种指令的执行时间是个比较复杂的问题,在此,只讨论一些一般的概念。
指令的基本执行时间因指令的不同而异,相互之间有很大的差异,而取、存操作数时间又因不同的寻址方式而有所不同。
当需要访问存储器以取得操作数时,还需要考虑计算有效地址EA所需要的时间。
表1~表3所列为执行不同指令所需的时间、执行加法指令时不同的寻址方式所需的时间,以及在不同的寻址方式下计算EA所需的时间。
在这些表格中,所有的时间都是以时钟周期数表示的。
表1指令的基本执行时间举例
指令
寻址方式
时钟周期数
加法ADD
寄存器—寄存器
3
传送MOV
寄存器—寄存器
2
整数乘法IMUL
16位寄存器乘
128~154
整数除法IDIV
16位寄存器除
165~184
移位
寄存器移1位
2
无条件转移JMP
直接
15
条件转移
不转移
4
转移
16
表2加法指令的执行时间
操作数的寻址方式
时钟周期数
访问存储器的次数
寄存器到寄存器
3
0
存储器到寄存器
9+EA
1
寄存器到存储器
16+EA
2
立即数到寄存器
4
0
立即数到存储器
17+EA
2
表3计算有效地址(EA)所需时间
寻址方式
时钟周期数
直接
6
寄存器间接
5
寄存器相对
9
基址变址
7~8
相对基址变址
11~12
另外,从表1~表3可以看出,不仅不同指令的执行时间差别很大,而且,当同一种指令使用不同寻址方式时,指令的执行时间差别也是很大的。
例:
假设时钟频率为5MHz,则一个时钟周期为0.2us,求下列指令的执行时间。
♦寄存器—寄存器方式,加法ADD指令。
则ADD指令的执行时间:
T=3×0.2=0.6us。
♦存储器—寄存器方式,若存储器使用相对基址变址寻址方式,则:
T=(9+EA)×0.2=(9+12)×0.2=4.2us。
如果在此种寻址方式下,求得的存储器有效地址为奇数,则根据IBMPC的规定,需要多访问一次存储器,即要增加4个时钟周期数,则t=(9+12+4)×0.2=5us
♦寄存器—存储器方式,此时,若存储器使用相对地址变址方式,则:
t=(16+EA)×0.2=(16+12)×0.2=5.6us。
如果此时求得的是奇地址,则需要时间为:
t=(16+12+8)×0.2=7.2us。
可见,即使是同一种ADD指令,不同的寻址方式也可以使它的执行时间相差一个数量级。
因此合理选择指令和寻址方式是很重要的,进而可知,用以完成同样功能的不同程序,在占用空间和执行时间上可能有很大的差别。
因此,在编制汇编程序时,如果对程序所占的存储空间或程序的执行时间要求不高,那么只需根据题意编制出合乎要求的程序就可以了(当然,如果能提高程序的空间效率和时间效率,则更为理想);若对程序所占有的存储空间或者对于执行的时间要求很高,那么应仔细斟酌程序算法、数据结构及指令与寻址方式的选用,以便编制出符合要求的程序。
§28086/8088的寻址方式
一、几个概念的说明
1.操作数的种类
⑴数据操作数
这类操作数是与数据有关的操作数,即指令中操作的对象是数据,数据操作数又可分为:
①立即数操作数—指令中要操作的数据在指令中。
②寄存器操作数—指令中要操作的数据存放在指定的寄存器中。
③存储器操作数—指令中要操作的数据存放在指定的存储单元中。
④I/O操作数——指令中要操作的数据来自或送到I/O端口。
⑵转移地址操作数
这类操作数是与转移地址有关的操作数,即指令中操作的对象不是数据,而是要转移的目标地址。
转移地址操作数也可分为:
立即数操作数、寄存器操作数、存储器操作数。
2.有效地址EA
当操作数是存放在存储器中时,存储器的存储单元的物理地址由两部分组成,一部分是偏移地址,一部分是段地址。
在8086/8088的各种寻址方式中,寻找存储单元所需的偏移地址可由各种成分组成,称为有效地址,用EA表示,不同的寻址方式,组成有效地址EA的各部分内容也不一样,详见后面的讨论说明。
3.段超越
存储器操作数寻址时,存储单元的物理地址的另一部分是段地址,对段地址是如何规定的呢?
8086/8088指令系统中对段地址有两个基本规定,即所谓的Default(默认)状态。
在正常情况下,由寻址方式中有效地址规定的基地址寄存器来确定段寄存器,即只要寻址方式中出现BP寄存器作为基地址,段寄存器一定采用堆栈段SS段寄存器。
其余的情况都采用DS段寄存器(注:
串处理指令有另外规定)。
物理地址=DS×16(10H)+偏移地址
指令中的操作数也可以不在基本规定的段区域,但是必须在指令中指定段寄存器,这就是段超越。
例:
MOVAL,[2000H];物理地址=DS×16+2000H
MOVAL,ES:
[2000H];物理地址=ES×16+2000H
段地址的基本规定和允许超越的情况如下表1所示:
表1段地址的基本规定和允许超越的情况
存储器存取方式
默认段
可“段超越”的段地址
段内偏义地址来源
取指令
CS
无
IP
堆栈操作
SS
无
SP
字符串操作原地址
DS
CS,ES,SS
SI
字符串操作目标地址
ES
无
DI
BP作基址
SS
CS,DS,ES
计算得的EA
通用数据读写
DS
CS,ES,SS
计算得的EA
二、与数据有关的寻址方式
8086/8088指令中数据(操作数)有7种寻址方式。
1.立即寻址方式(Immediateaddressing)
操作数直接存放在指令中,紧跟在操作码之后,它作为指令的操作码字段存放在指令代码中,这种数称为立即数。
立即数可以是8位的或16位的,如果是16位立即数,则低位字节数存放在低地址单元中(紧跟在操作码之后),高位字节数存放在高地址单元中。
指令码存放形式所示:
16位
代码段
代码段
OP
D8
操作码
指令码
操作数
8位
操作数
例1:
MOVAL,05H;AL←05H
指令执行后,AL=05H,8位数据05H存入AL寄存器。
操作的示意图如图所示。
指令功能、指令执行过程演示见PPT文档。
MOVAL,05操作示意图
例2:
MOVAX,1234H;AX←1234H
指令执行后,AX=0102H,16位数据存入AX寄存器,其中(AH)=12H,(AL)=34H。
操作示意图如图所示。
指令功能、执行过程演示见PPT文档。
例3:
MOVAX,COUNT;AX←COUNT
在汇编语言指令中,可以用符号COUNT代替常数,但是COUNT必须用伪指令EQU来赋值。
立即数寻址方式主要用来对寄存器赋值,由于在执行的过程中,立即数可以从指令队列中直接取得,CPU不必执行总线周期,指令执行速度快。
注:
立即数只能是整数,只能作为源操作数。
2.寄存器寻址方式(Registeraddressing)
操作数在寄存器中,指令指定寄存器号。
对于16位操作数,寄存器可以是AX,BX,CX,DX,SI,DI,SP和BP等;对于8位操作数,寄存器可以是AH,AL,BH,BL,CH,CL,DH和DL等。
这种寻址方式由于操作数在寄存器中,不需要访问存储器来取得操作数,因而可以取得较高的运算速度。
寄存器
这种寻址方式寻找操作数的示意图如下:
例:
MOVAX,BX;AX←BX
若指令执行前,AX=3064H,BX=1234H
则指令执行后,AX=1234H,BX=1234H
指令功能、执行过程演示见PPT文档。
除上述两种寻址方式以外,以下介绍的各种寻址方式的操作数都是存放在代码段以外的存储器区段中。
3.直接寻址方式(Directaddressing)
在直接寻址方式中,有效地址EA就在指令代码中,它存放在代码段中指令操作码后面的操作数字段,指令码表示如图。
此寻址方式与立即寻址方式相比较,在指令代码中,直接寻址的操作数字段是偏移地址,立即寻址的操作数字段是立即数。
由于操作数在正常情况下是存放在数据段中,所以必须先求出操作数的物理地址,然后再按照此地址访问存储器才能取得或存入数据。
其寻址方式示意图如图所示。
操作数物理地址(PA)为:
PA=DS×10H+EA
8086/8088允许数据存放在数据段以外的其它段中,此时在指令中应指定段超越的段寄存器名,在计算物理地址时应使用指定的段寄存器。
例1:
MOVAX,[1000H];将有效地址EA=1000H单元中的内容传送到AX寄存器。
如DS=2000H,从指令可知,EA=1000H。
存放源操作数的存储单元的物理地址为:
PA=DS×10H+EA=20000+1000=21000H。
假设指令执行前,AX=7850H,
(21000H)=78H,(21001H)=56H。
指令执行后:
AX=5678H,
(21000H)=78H,(21001H)=56H。
指令执行情况如图所示。
命令功能、执行过程演示见PPT文档。
在汇编语言中,可用符号地址代替数值地址,如:
例2:
MOVAX,VALUE
其中VALUE即为存放源操作数的符号地址(有效地址EA),需用伪地址定义,此指令也可写成:
MOVAX,[VALUE]。
源操作数的存储单元也可以存放在其它段中,但必须在指令中指定段超越前缀,如:
MOVAX,ES:
[2000H]
MOVAX,SS:
VALUE
4.寄存器间接寻址方式(Registerindirectaddressing)
操作数的有效地址在基址寄存器BX,BP或变址寄存器SI,DI中,操作数则在存储器中,此种寻址方式示意图如图所示。
如果指令指定的寄存器是BX,SI和DI,则操作数必定在数据段中,以DS段寄存器的内容作为段地址,操作数的物理地址为:
PA=16×DS+BX
或PA=16×DS+SI
或PA=16×DS+DI
如指令中指定的寄存器是BP,则操作数必定在堆栈段中,以SS段寄存器的内容作为段地址,操作数的物理地址为:
PA=16×SS+BP
例1:
MOVAX,[BX]
若DS=2000H,BX=1000H,则PA=20000+1000=21000H。
指令执行前:
AX=8040H,(21000H)=A0H,(21001H)=50H
指令执行后:
AX=50A0H,(21000H)=A0H,(21001H)=50H
例1执行情况示意如图所示。
命令功能、执行过程演示见PPT文档。
指令中也可以指定段超越前缀来使操作数存放在其它段中。
如:
例2:
MOVAX,SS:
[BX]
这时PA=16×SS+BX
这种寻址方式适用于表格处理,执行完一条指令后,只需修改寄存器内容,就可以取出表格中的下一项。
5.寄存器相对寻址(Registerrelativeaddressing)(或称直接变址寻址)
操作数的有效地址是一个基址或变址寄存器的内容和指令中指定的8位或16位偏移量(displacement)之和。
对于BX,SI,DI寄存器,段寄存器用DS,对于BP寄存器,段寄存器用SS,其物理地址(PA)为:
或
这种寻址方式示意如图所示。
例1:
MOVAX,disp[SI]或MOVAX,[SI+disp]
其中disp为16位偏移量,它是符号地址。
实际上disp究竟是8位还是16位偏移量,可由伪指令来定义。
如DS=3000H,SI=2000H,disp=3000H。
则EA=SI+disp=2000H+3000H=5000H
物理地址PA=16×DS+EA=30000H+5000H
=35000H
指令执行前:
AX=7A6CH,(35000H)=34H,(35001H)=12H。
指令执行后:
AX=1234H,(35000H)=34H,(35001H)=12H。
例1执行情况示意如图所示。
命令功能、执行过程演示见PPT文档。
同样,这种寻址方式也可采用段超越。
如:
例2:
MOVDL,ES:
disp[DI]
则:
EA=disp+di,PA=16×ES+disp+DI
这种寻址方式也适用于表格处理。
6.基址变址寻址方式(Basedindexedaddressing)
操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和。
两个寄存器均由指令指定。
如基址寄存器为BX,段寄存器使用DS;基址寄存器为BP,段寄存器使用SS。
因此物理地址为:
物理地址=16×DS+BX+SI;物理地址=16×DS+BX+DI
物理地址=16×SS+BX+SI;物理地址=16×SS+BX+DI
这种寻址方式如下图:
例1:
MOVAX,[BX][DI]或MOVAX,[BX+DI]
如DS=3000H,BX=6780H,DI=0041H。
则EA=6780H+0041H=67C1H,
源操作数存放单元的物理地址为:
PA=30000H+67C1H=367C1H。
指令执行前:
AX=8957H,(367C1H)=34H,(367C2H)=12H。
指令执行后:
AX=1234H,(367C1H)=34H,(367C2H)=12H。
例1执行情况示意如图所示。
这种寻址方式使用段超越的格式为:
例2:
MOVAX,ES:
[BX][SI]
此寻址方式适用与数组和表格处理。
命令功能、执行过程演示见PPT文档。
7.相对基址变址寻址(Relativebasedindexedaddressing)
操作数的有效地址是一个基址寄存器内容,一个变址寄存器的内容和8位或16位偏移量之和。
当基址寄存器为BX,段寄存器用DS;
基址寄存器为BP,段寄存器用SS。
其物理地址为:
这种寻址方式的寻址示意如图所示。
例1:
MOVAX,disp[BX][SI]
或MOVAX,disp[BX+SI]
或MOVAX,[disp+BX+SI]
如DS=5000H,BX=1C7AH,SI=0135H,disp=0200H。
则物理地址为:
物理地址=50000H+1C7AH+0135H+0200H
=51FAFH
指令执行前:
AX=765AH,(51FAFH)=78H,(51FB0H)=56H。
指令执行后:
AX=5678H,(51FAFH)=78H,(51FB0H)=56H。
这种寻址方式为堆栈处理提供了方便,一般BP可指向栈顶,从栈顶到数组的首地址可用偏移量表示,变址寄存器可用来访问数组中的某个元素。
例1执行情况示意如图所示。
命令功能、执行过程演示见PPT文档。
练习:
若:
BX=0158H,DI=10A5H,偏移量(disp)=1B57H,DS=2100H,SS=1100H,BP=0100H,段寄存器按默认段寄存器,计算相对于存储器寻址的各种寻址方式的有效地址和物理地址。
解:
①直接寻址:
EA=1B57H;PA=16×DS+EA=21000H+1B57H=22B57H
②寄存器间接寻址(设寄存器为BX):
EA=0158H;PA=16×DS+EA=21000H+0158H=21158H
③寄存器相对寻址(设寄存器为BP):
EA=BP+disp=0100H+1B57H=1C57H
PA=16×SS+EA=11000H+1C57H=12C57H
④基址变址寻址(设寄存器为BX和DI):
EA=BX+DI=0158H+10A5H=11FDH
PA=16×DS+EA=21000H+11FDH=221FDH
⑤基址变址相对寻址(设寄存器为BP和DI):
EA=BP+DI+disp=0100H+10A5H+1B57H=2CFCH
PA=16×SS+EA=11000H+2CFCH=13CFCH
三、与转移地址有关的寻址方式P38
§38086/8088指令系统
8086/8088CPU指令系统分为7大类(传送指令、算术指令、逻辑运算和移位指令、串操作指令、程序控制指令、处理器控制指令)。
一、数据传送类指令
数据传送类指令是指令系统中用得最多的一类指令,也是条数最多的一类指令(14条),常用于将原始数据、中间运算结果、最终结果及其他信息在CPU的寄存器和存储器之间进行传送。
根据功能的不同,数据传送类指令可分为:
•通用数据传送指令:
MOV
•交换指令:
XCHG
•堆栈操作指令:
PUSH,POP
•地址传送操作指令:
LEA,LDS,LES
•标志寄存器传送指令:
LAHF,SAHF,PUSHF,POPF
•累加器专用传送指令:
IN,OUT,XLAT
1.通用数据传送指令
MOV传送指令
格式:
MOVDST,SRC
执行的操作:
(DST)(SRC)
其中DST表示目的操作数,SRC表示源操作数。
功能:
此指令把一个字节或一个字操作数从源传送到目的,源操作数内容未变,目的操作数内容和源操作数内容相同。
MOV指令有九种形式,如图所示。
①从累加器送到存储器
格式:
MOVMEM,AC;(mem)ac(ac表示AX,AH,AL)
②从存储器送累加器
格式:
MOVAX,DISP[BP][SI];把地址SS×10H+(BP)+(SI)+DISP存储单元的内容送AX
③从存储器或寄存器送到段寄存器
格式:
MOVsegreg,mem/reg;segreg(mem/reg)
其中segreg表示不包括CS的段寄存器(SS,DS,ES),本指令只能是字操作。
④从段寄存器到寄存器或存储器
格式:
MOVmem/reg,segreg;(mem/reg)segreg
规定同③,但segreg包括CS,即CS,SS,DS,ES。
⑤从寄存器到寄存器
格式:
MOVreg1,reg2;reg1reg2
注:
两个寄存器之间传送时,只能相同字长的寄存器之间传送,不能在不同字长寄存器之间传送。
⑥从寄存器到存储器
格式:
MOVmem,reg;(mem)reg
此指令可以是字操作,也可以是字节操作。
⑦从存储器到寄存器
格式:
MOVreg,mem;reg(mem)
与⑥传送方向相反,规定相同。
⑧立即数送寄存器
格式:
MOVreg,data;regdata
8位
Data立即数,ASCII字符。
Data数据类型必须与寄存器字长相一致。
8位数
16位
可以送16位寄存器,但16位数不能送8位寄存器。
⑨立即数送存储器
格式:
MOVmem,data;(mem)dataBYTEPTR字节操作
规定同⑧,但对mem存储操作数必须作数据类型说明。
WORDPTR字操作
注意点:
⏹MOV指令的目的操作数不允许用立即数方式,也不允许使用CS段寄存器,而且除源操作数为立即数的情况外,两个操作数中必须有一个是寄存器。
不允许mem直接之间传送;也不允许在两个段寄存器之间直接传送。
⏹MOV指令不影响标志位。
例1:
立即数送通用寄存器或存储器
MOVAL,55H
MOV