11
3.3 8086/80883.3 8086/8088 指令系统指令系统
可分成如下 6 类: 数据传送指令 算术运算指令 逻辑运算和移位指令 串操作指令 程序控制指令 处理器控制指令
22
3.3.1 3.3.1 数据传送指令数据传送指令 可实现
存储器 寄存器 I/O 数据传送指令又可分为如下四种:
通用传送 目标地址传送 标志传送 输入输出
33
1. 通用传送指令(1) MOV dest , src ; dest←src 传送的是字节还是字取决于指令中涉及的寄存器是 8 位还是 16 位。 具体来说可实现: ① MOV mem/reg1 , mem/reg2 指令中两操作数中至少有一个为寄存器 例 : MOV CL , DL MOV AX , BX
MOV [SI] , CXMOV CL , [BX+5]
44
② MOV reg , data ; 立即数送寄存器
③ MOV mem , data ; 立即数送存储单元
④ MOV acc , mem ; 存储单元送累加器
⑤ MOV mem , acc ; 累加器送存储单元
⑥ MOV segreg , mem/reg ; 存储单元 / 寄存器送 段寄存器⑦ MOV mem/reg , segreg ; 段寄存器送存储单 元 / 寄存器
55
MOVMOV 指令使用规则:指令使用规则:
1) IP 不能作目的寄存器2) 不允许 mem←mem3) 不允许 segreg←segreg4) 立即数不允许作为目的操作数5) 不允许 segreg← 立即数6) 源操作数与目的操作数类型要一致
66
几个不能传送的解决办法:用 AX 作桥梁
存储器←存储器: MOV AX , MEM1
MOV MEM2 , AX段寄存器←段寄存器: MOV AX , DS
MOV ES , AX段寄存器←立即数: MOV AX , DATA
MOV DS , AX
77
应用举例:将 1000H 开始的 100 个存储单元 全部填充为 ASCII 码 2AH(*) 。程序段如下: MOV DI , 1000H MOV CX , 64H MOV AL , 2AHAGAIN : MOV [DI] , AL INC DI DEC CX JNZ AGAIN HLT
88
上程序段存放在代码段中 , 設 (CS)=109EH, 则各条指令存放地址如下: CS : IP 指令109E : 0100 MOV DI , 1000H109E : 0103 MOV CX , 64H109E : 0106 MOV AL , 2AH109E : 0108 MOV [DI] , AL109E : 010A INC DI109E : 010B DEC CX109E : 010C JNZ 0108109E : 010E HLT109E : 0110
99
写入 2AH(*) 后,数据段中相应存储单元的内容改变如下:
DS:1000 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1010 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1020 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1030 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1040 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1050 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2ADS:1060 2A 2A 2A 2A
1010
什么是堆栈? 按“后进先出 (LIFO)” 方式工作的存储区域。堆栈以字为单位进行压入弹出操作。
为什么要设置堆栈?为什么要按 “后进先出”方式工作?参见下图
(2) (2) 堆栈操作指令堆栈操作指令
1111
主程序
IP
继续执行
主程序
执行子程序
转子程序
压栈
弹出返回主程序
主程序
IP
IP( 下 )
继续执行
主程序
转子程序 1
返回主程序
IP’
执行子程序 2
转子程序 2
返回子程序1
IP’( 下 )
执行子程序 1
继续执行
子程序1
(a) (b)子程序调用示意图
(a) 主程序调子程序; (b) 子程序嵌套示意图
压栈
弹出IP( 下 )
1212
规定由 SS 指示堆栈段的段基址,堆栈指针 SP始终指向堆栈的顶部, SP 的初值规定了所用堆栈区的大小。堆栈的最高地址叫栈底。
SP
SS
堆栈段进栈方向
退栈方向栈底
栈顶
1313
① 压栈指令 PUSH src ; src 为 16 位操作数
例: PUSH AX ;将 AX 内容压栈 执行操作:( SP ) -1← 高字节 AH
( SP ) -2← 低字节 AL
(SP )←( SP ) - 2
1414
设( AX ) =1020H ,执行示意图如图
低地址 存储区
( SS段)
执行前
(AX)=1020
(SP)
存储区
( SS段)
进栈方向
执行后
20
10
(AL)
(AH)
2-8
PUSH AX 指令执行示意图
(SP)-2
(SP)
高地址
低地址
高地址
(SP)-1
1515
压栈指令的格式为: PUSH reg PUSH mem/reg PUSH segreg例如: PUSH AX PUSH [BX] PUSH DS
注意进栈方向是注意进栈方向是高地址高地址向向低地址低地址发展。发展。
1616
② 弹出指令 POP dest
例: POP BX ;将栈顶内容弹至 BX 执行操作: ( BL )←( SP ) ( BH )←( SP ) +1 ( SP )←( SP ) +2
1717
POP BX 的执行示意图如下图所示
低地址
存储区
( SS段)
出栈方向
执行前
20
10
POP BX 指令执行示意图
(SP)
存储区
( SS段)
执行后
(BX)=1020
(SP)(SP)+1
(SP)+2
BX
20
10
高地址
低地址
高地址
1818
堆栈指令使用时应注意几点:
① 堆栈操作总是按字进行② 不能从栈顶弹出一个字给 CS③ 堆栈指针为 SS:SP , SP 永远指向栈顶④SP 自动进行增减量( -2 , +2 )
1919
格式: XCHG reg , mem/reg功能:交换两操作数的内容。 要求:两操作数中必须有一个在寄存器中; 操作数不能为段寄存器和立即数; 源和目地操作数类型要一致。举例: XCHG AX , BX XCHG [2000] , CL
(3)(3) 交换指令交换指令 XCHGXCHG
2020
(4) 查表指令 XLAT 执行的操作: AL←[(BX)+(AL)] 又叫查表转换指令,它可根据表项序号查出表中对应代码的内容。执行时先将表的首地址(偏移地址)送到 BX 中,表项序号存于 AL 中。 例如:内存数据段有一张 16 进制数的 ASCII 码表,设首地址为 2000H ,如欲查出表中第 11 个代码(代码序号从 0 开始)即十六进制数 B 的 ASCII 码。 ASCII 表在 DS段中,并假设 (DS)=4000H 。见下页图。
‘ ’
2121
30
31
32...39
41
42...45
46...
42000H+0
42000H+0BH
‘0’
‘1’
‘2’
‘9’
‘A’
‘B’
‘E’
‘F’
十六进制数 ASCII 码表
存储器
2222
则可用如下几条指令实现:
MOV BXMOV BX ,, 2000H2000H ;(;( BXBX )←表首地址)←表首地址MOV ALMOV AL ,, 0BH0BH ;(;( ALAL )←序号)←序号XALTXALT ; 查表转换; 查表转换
执行后得到:(执行后得到:( ALAL )) = 42H = = 42H = ’ ’ BB’’
注意:转换表长度最大为 256 个表项 ( 字节 ) 。
2323
(5)(5) 字节字节 -- 字转换指令字转换指令格式: CBW ; 把 AL 的符号位复制到 AH
CWD ; 把 AX 的符号位复制到 DX
用途:用于有符号数的除法。例如: (AL) = A7H ,则执行 CBW 后, AH
的内 容为 FFH 。
2424
2. 2. 输入输出(输入输出( I/OI/O )指令)指令 只限于用累加器 AL或 AX 来传送信息。功能 : (累加器 )←→I/O端口(1) 输入指令 IN格式 : IN acc,PORT ;PORT端口号 0~ 255 IN acc,DX ;DX 表示的端口范围达 64K例 :IN AL , 80H ;(AL )← (80H端口 ) IN AL , DX ;(AL )← ((DX))
2525
例: OUT 68H , AX ;(69H , 68H )←( AX ) OUT DX , AL ;((DX))←(AL)在使用间接寻址的 IN/OUT 指令时,要事先用传送指令把 I/O端口号设置到 DX 寄存器,如: MOV DX , 220H IN AL , DX ; 将 220H端口内容读入 AL
(2) (2) 输出指令输出指令 OUTOUT
格式:格式: OUT port,accOUT port,acc OUT DX,acc OUT DX,acc
2626
3. 地址传送指令共有三条 :格式: LEA reg , mem ; 将指定存储器的 16 位偏移 地址送指定寄存器 LDS reg, mem32; DS:reg←(mem 开始的四 个内存单元 ) LES reg, mem32; 同上,但 DS 改为 ES 要求源操作数必须是一个内存操作数,目的操作数必须是一个 16 位的通用寄存器。
2727
设:( SI ) =1000H则执行该指令后,( BX ) =1010H
注意以下两条指令差别: LEA BX , BUFFER MOV BX , BUFFER前者表示将符号地址为 BUFFER的存储单元的偏侈地址取到 BX 中 ; 后者表示将 BUFFER存储单元中的内容取到 BX 中 .
例:例: LEALEA BXBX ,, [SI+10H][SI+10H]
2828
下面两条指令等效:
LEA BX , BUFFER MOV BX, OFFSET BUFFER
其中 OFFSET BUFFER表示存储器单元 BUFFER的偏移地址。二者都可用于取存储器单元的偏移地址,但LEA 指令可以取动态的地址, OFFSET只能取静态的地址。
2929
4.标志传送指令共有四条:
(1) 读标志指令 LAHF
LAHF把标志寄存器低 8 位中的 5 个标志位传送到 AH 中的指定位,如下图所示 :
1D3D5D7D 6D 4D 2D 0D
OF DF IF TF SF ZF AF PF CF
AH
LAHF指令的功能
FLAG
3030
(2) 设置标志指令 SAHF SAHF 的功能与 LAHF 的功能正好相反,用图来示意,只要将上图中 5 个箭头方向反一下即可。
1D3D5D7D 6D 4D 2D 0D
OF DF IF TF SF ZF AF PF CF
AH
SAHF指令的功能
FLAG
3131
执行的操作 :(SP)-1← 标志寄存器高 8 位 (SP)-2← 标志寄存器低 8 位 (SP)←(SP)-2(4) 从栈顶弹出标志寄存器指令 POPF
执行的操作 : 标志寄存器低 8 位← (SP) 标志寄存器高 8 位← (SP)+1
(SP)←(SP)+2PUSHF 和 POPF 指令用于保护和恢复标志寄存器内容。
(3)(3) 把标志寄存器推入栈顶指令把标志寄存器推入栈顶指令 PUSHFPUSHF
3232
例如: PUSH AX PUSH CX PUSHF ;保护标志寄存器内容 ;这段程序要用到 AX,CX以及标志位 POPF ;恢复标志寄存器内容 POP CX POP AX
. . .
3333
数据传送指令中,除 SAHF 和 POPF这两条指令外,其余所有指令均不影响标志位。
3434
3.3.2 3.3.2 算术运算指令算术运算指令 涉及两种类型数据 : 无符号数和有符号数。对加减法指令,无符号和有符号数可采用同一套指令,但应注意: 参加的操作数必须都是无符号数或都是有符号数。 需使用不同的标志位来检查无符号数和有符号数的运算结果是否溢出。
3535
• 两个 8 位数相加时有 4 种情况:① 无符号数和有符号数均不溢出
二进制相加 无符号数加 有符号数加 0000 1000 8 +8+0001 1110 + 30 + (+30) 0010 0110 38 +38 结果 38 CF=0 OF=0
3636
② 无符号数溢出 0000 1000 8 +8+1111 1101 +253 +(-3)10000 0101 261 +5 结果 5 CF=1 OF=0③ 有符号数溢出 0000 1000 8 +8+0111 1101 +125 + ( +125 ) 1000 0101 133 +133结果 -123 CF=0 OF=1
(补码表示)
3737
④ 无符号数和有符号数均溢出 1000 1000 136 -120+1111 0111 +247 + ( -9 )10111 1111 383 -129 结果 127 CF=1 OF=1
上面四种情况说明, CF 标志可用来表示无符号数的溢出, OF 标志可用来表示有符号数的溢出。
有符号数的溢出是一种出错状态,在运算过程中应当避免。
3838
共有 5 条 :(1) 不带进位的加法指令 ADD 格式: ADD acc,data ADD mem/reg,data ADD mem/reg1,mem/reg2例: ADD AL , 30H ADD AX , [BX+20H] ADD CX , SI ADD [DI] , 200HADD 指令对标志位(指状态标志)都有影响。
1.1. 加法指令加法指令
3939
(2) (2) 带进位位的加法指令带进位位的加法指令 ADCADC
ADC 指令在形式上和功能上都有与 ADD 类似,只是相加时还要包括进位标志 CF 的内容,例如: ADC AL , 68H ;AL←(AL)+68H+(CF) ADC AX , CX ;AX←(AX)+(CX)+(CF) ADC BX , [DI] ;BX←(BX)+[DI+1][DI] +(CF)
4040
例 : 有两个 4 字节的无符号数相加: 2C56F8AC+309E47BE= ? 设被加数、加数分别存放在 BUFFER1 及 BUFFER2 开始的两个存储区内,结果放回 BUFFER1 存储区,如下页图所示。 因 CPU只能进行 8 位或 16 位的加法运算,为此可将加法分 4次进行。
ADCADC 指令主要用于多字节加法运算中指令主要用于多字节加法运算中
4141
56H
2CH
BEH
47H
BUFFER1
BUFFER2
ACH
F8H
9EH
30H
被加数
加数
数据段
多字节加法示意图 ...
...
4242
程序段如下: MOV CX , 4 ; 置循环次数 MOV SI , 0 ; 置 SI 初值为零 CLC ;清进位标志 CFLL : MOV AL , BUFFER2[SI] ADC BUFFER1[SI] , AL ;带进位加 INC SI ;(SI)+1 DEC CX ;(CX)-1 JNZ LL ;若 (CX)0, 则转 LL