2. 减法指令 8086/8088 共有 5 条减法指令 1 不带 CF 的减法指令 (SUB) 格式 :SUB DST, SRC 功能 :(1)DST (DST)-(SRC) (2) 根据差设置 6 个状态标志
2 带 CF 的减法指令 (SBB) 格式 :SBB DST, SRC 功能 : (1)DST (DST)-(SRC)-CF (2) 根据差设置 6 个状态标志
3 减 1 指令 (DEC) 格式 :DEC DST 功能 : (1)DST (DST)-1, (2) 根据差设置除 CF 以外的 6 个状态标志, 对 CF 无影响
4 取负指令 (NEG) 格式 :NEG DST 功能 : DST 0-(DST), NEG 指令完成的是特殊的减法操作, 它的被减数一定为零, 因此它是一条单操作数指令
实际它是将目的操作数的值取负 若操作数的原值为一正数, 那么, 执行该指令后, 其值变为该数的负数的补码 ; 而若操作数的原值为一负数 ( 补码表示 ), 那么, 执行该指令后, 其值变为该数所对应的正数 该指令将正常影响各标志位, 并且 CF 表示最高位产生的借位 指令中的目的操作数可以采用除立即数以外的各种寻址方式
例 1: 若 (AL)=03H, 则 CPU 执行 NEG AL 指令后, (AL)=0FDH -3 的补码 ` ` ` ` 0 0 0 0 0 0 0 0 B - 0 0 0 0 0 0 1 1 B [1]1 1 1 1 1 1 0 1 B 结果为 -3 的补码 AF=1 PF=0 ZF=0 SF=1 CF=1 OF=0
若 (AL)=0FDH, 则 CPU 执行 NEG AL 指令后, (AL)=03H - +3 的补码 ` ` ` ` 0 0 0 0 0 0 0 0 B 1 1 1 1 1 1 0 1 B [1]0 0 0 0 0 0 1 1 B 结果为 +3 的原码 ( 补码 ) 应用场合 : 常常用于求某数的绝对值的场合
5 比较指令 (CMP) 格式 :CMP DST,SRC 功能 :(1)(DST) (SRC) (2) 根据差设置 6 个状态标志位
与减法指令不同的是所产生的两数之差并不取代目的操作数, 因而指令执行后, 仅仅改变了标志寄存器的内容, 两操作数的值保持不变
应用场合 : 两操作数参加比较, 根据比较结果确定两操作数之间的关系 ( 如等于 大于 小于等 ) 在分支程序设计中, 用来产生条件, 其后往往紧跟的是一条条件转移指令
如 : CMP DST,SRC Y P2 条件满足吗? N P1 条件有 ZF SF CF OF PF
程序中的表现形式为 : CMP AL,0 JZ L1 L1:
在此, 结合 CMP 指令的应用, 简 要介绍一下 8086 指令系统中的条件 转移指令 ( 见教材 P109-111)
例. 有两数 Α 和 Β, 则 CPU 执行下列指令组 MOV AL,Α CMP AL,Β ;(AL) Β, 根据差 ; 设置 6 个状态标志 后, 要实现条件转移, 根据不同的条件, 有不同的条件转移指令
根据单个条件标志实现转移 ZF SF 1, JZ/JE 标号 测试条件 :ZF=1 0,JNZ/JNE 标号 测试条件 :ZF=0 1, JS 标号 测试条件 :SF=1 0, JNS 标号 测试条件 :SF=0
OF PF CF 1, JO 标号 测试条件 :OF=1 0, JNO 标号 测试条件 :OF=0 1, JP 标号 测试条件 :PF=1 0, JNP 标号 测试条件 :PF=0 1, JC 标号 测试条件 :CF=1 0, JNC 标号 测试条件 :CF=0
若 Α Β 为两个无符号数, 根据比较结果实现转移 Α=Β JE/JZ 标号 测试条件 : ZF=1 Α 低于 Β( 或 Α 不高于或不等于 Β) JB/JC/JNAE 标号测试条件 : CF=1
Α 不低于 Β( 或高于或等于 ) JNB/JAE/JNC 标号测试条件 :CF=0 Α 高于 Β( 或不低于或不等于 ) JA/JNBE 标号测试条件 :CF ZF=0 Α 不高于 Β( 或低于或等于 ) JNA/JBE 标号测试条件 :CF ZF=1
若 Α Β 为两个带符号数, 根据比较结果实现转移 Α=Β JE/JZ 标号 测试条件 : ZF=1 Α 小于 Β( 或 Α 不大于或不等于 Β) JL/JNGE 标号测试条件 :SF OF=1
Α 不小于 Β( 大于或等于 ) JNL/JGE 标号测试条件 :SF OF=0 Α 大于 Β( 不小于或不等于 ) JG/JNLE 标号测试条件 :(SF OF) ZF=0 Α 不大于 Β( 小于或等于 ) JNG/JLE 标号测试条件 :(SF OF) ZF=1
测试 CX 的值为 0 则转移 JCXZ 标号 测试条件 : (CX)=0 下面举例说明比较指令 (CMP) 和条件转移指令的用法
例 1. 设在存储器 BUFFER 单元存放着一个字节的带符号数 X, 求 X 的绝对值, 并将结果放回原处 (P98 例 4.3.3) 算法 : X = X,; 当 X 0 时 -X,; 当 X<0 时
流程图 : AL (BUFFER) Y X 0? N 求负 (BUFFER) (AL) 程序 : MOV AL,BUFFER CMP AL,0 JNS NONEG NEG AL NONEG:MOV BUFFER,AL
例 2: 符号函数的处理 有一符号函数 : Y= 1, 当 X>0 时 (-128 X +127) 0, 当 X=0 时 -1, 当 X<0 时 设给定值 X 存放在 XX 单元, 函数 Y 值 存放到 YY 单元
流程图 : 程序 : (AL)=0? N AL 1 Y Y AL (XX) (AL) 0? N (AL) -1 (YY) (AL) MOV AL,XX CMP AL,0 JGE BIGR MOV AL,-1 JMP EQUL BIGR:JE EQUL MOV AL,1 EQUL:MOV YY,AL
3. 乘法指令 (MUL/IMUL) 乘法指令分带符号运算和不带符号运算两种 带符号运算时, 操作数和结果均以补码表示, 结果的符号按一般的运算规则确定 无符号数乘法指令 (MUL) 格式 :MUL SRC 不能为立即数
功能 : DST( 被乘数 ) SRC( 乘数 ) 字节乘 : AX 积 (AL) * (SRC) 字乘 : DX:AX 积 (AX) * (SRC) 操作类型 : 用 SRC 的类型确定 乘法指令只影响 CF 和 OF 标志, 其余标志均无意义
其中, CF=0 OF=0 CF=1 OF=1 表明结果的高位字节 ( 或字 ) 为全 0 表明结果的高位字节 ( 或字 ) 有有效积
带符号数乘法指令 (IMUL) 格式 :IMUL SRC 不能为立即数
功能 : DST( 被乘数 ) SRC( 乘数 ) 字节乘 : AX 积 (AL) * (SRC) 字乘 : DX:AX 积 (AX) * (SRC) 操作类型 : 用 SRC 的类型确定 乘法指令只影响 CF 和 OF 标志, 其余标志均无意义
其中, CF=0 OF=0 CF=1 OF=1 表明结果的高位字节 ( 或字 ) 仅仅是低位字节 ( 或字 ) 的符号扩展 表明结果的高位字节 ( 或字 ) 有有效积
总之, 乘法指令中的目的操作数一定为 AL(8 位数相乘 ) 或 AX (16 位数相乘 ), 源操作数不能为立即数, 但可采用其它寻址方式, 指令对字节运算还是字运算由源操作数的类型确定
例 1. 下列指令是合法的 MUL CX ;(DX:AX) (AX)*(CX), 为字操作 IMUL CL ;(AX) (AL)*(CL), 为字节操作下列指令是非法的 MUL AL,BL 〤 DST( 被乘数 ) 应为隐含寻址 IMUL 05H 〤 SRC( 乘数 ) 不能为立即数寻址
例 2. 若 (AL)=05H,(BL)=0FDH 则 CPU 执行 : MUL BL ; 无符号数乘法 ;(AL)*(BL) 积 AX ; (AX)=04F1H
则 CPU 执行 : IMUL BL ; 带符号数乘法 ;(AL)*(BL) 积 AX ; 05H*0FDH=0FFF1H [-3] 补 ; (AX)=0FFF1H ( 即 [-15] ) 补
4. 除法指令 (DIV/IDIV) 除法指令和乘法指令一样, 分无符号除法和带符号除法 操作类型有字节除法和字除法, 其操作类型取决于 SRC( 除数 ) 的类型 无符号数除法指令 (DIV) 格式 :DIV SRC
带符号数除法指令 (IDIV) 格式 :IDIV SRC 其中,DST 为隐含寻址 ( 作被除数 ) 字节除时, 被除数一定在 AX 中字除时, 被除数一定在 DX:AX 中 SRC( 除数 ) 不能为立即数
功能 : 字节除法 : (AX)/(SRC) 商 余数 AL AH 字除法 : (DX:AX)/(SRC) 商 余数 AX DX
除法运算后, 标志位没有意义 除法不允许出现除数为 0 或商溢出, 若发生除数为 0 或商溢出则其结果没有意义, 并引起中断 ( 关于中断的概念以后再作介绍 )
例 1. 下列指令是合法的 DIV BL IDIV CX DIV WORD PTR [BX][SI] 下列指令是非法的 DIV 12 〤 SRC( 除数 ) 不能为立即数寻址 DIV [SI]+02H 〤 SRC 类型不明确 IDIV AX,BL 〤 DST( 被除数 ) 应为隐含寻址
例 2. 在存储器 HEX 单元存放着一个字节的无符号二进制数, 试将其转换成十进制数以分离 BCD 数形式存到 BCD1 以下存储单元 ( 设个位存在低地址单元 )
分析题目 HEX BCD1 66H??? 个位十位百位
确定算法 : 用除 10 取余法 即用被转换的数除以 10, 第一次得到的余数为转换后的十进制数的个位数, 用中间商再除以 10, 得到的余数为转换后十进制数的十位数, 最后的商为十进制数的百位数
流程图 : START AL (HEX) AH 0 BL 10 SI OFFSET BCD1 (AX)/(BL) ((SI)) AH AH 0 (AX)/(BL) ((SI)+1) (AH) ((SI)+2) (AL) 结束
程序 : ; 在数据段定义变量如下 : HEX DB 66H BCD1 DB 3 DUP (?) ; 在代码段编写程序 MOV AH,0 MOV AL,HEX MOV BL,10 MOV SI,OFFSET BCD1 DIV BL MOV [SI],AH MOV AH,0 DIV BL MOV [SI]+1,AH MOV [SI]+2,AL...
程序执行后存储器示意图 HEX BCD1 66H 02H 00H 01H 个位十位百位
5. 符号扩展指令 (CBW/CWD) 格式 : CBW 功能 : 将 AL 中的符号扩展到 AH 中, 即将一个字节的带符号数 扩展成一个字
格式 : CWD 功能 : 将 AX 中的符号扩展到 DX 中, 将一个字的带符号数扩展 成双字
应用场合 : 在算术运算中, 有时会遇到两个长度不等的数进行加 减运算, 此时, 应将长度短的数的位数扩展, 以使两数的长度一致, 只有这样, 才能保证参加运算的两个操作数的类型是一致的 对于一个无符号数来说, 这种扩展是简单的, 只要将其高位补 0 就可以 ; 但对一个带符号数来说就不一样了, 高位扩展时, 补 0 还是补 1 就取决于该数的符号位
例 1. 若 (AL)=05H, 则 CPU 执行 CBW 后, (AX)=0005H 若 (AL)=0FDH, 则 CPU 执行 CBW 后, (AX)=0FFFDH [-3] 补
例 2. 写出计算 Y=a*b+c-18 的程序 (P102 例 4.3.1) ; 在数据段定义变量如下 : DAT1 DB 34H ;34H 为变量 a 的一个设定值 DAT2 DB 56H ;56H 为变量 b 的一个设定值 DAT3 DB 0E7H ;0E7H 为变量 c 的一个设定值 DATY DW? ;DATY 单元存放结果
; 在代码段编写程序 MOV AL,DAT1 ; 取 a MOV BL,DAT2 ; 取 b IMUL BL ;(AL)*(BL) (AX) MOV BX,AX ;(AX) (BX) MOV AL,DAT3 ; 取 c CBW ; 扩展 AL AX ADD AX,BX ;(AX)+(BX) (AX) SUB AX,18 MOV DATY,AX Y=a*b+c-18
作业 :P186 188 1. 2. 3.(1)---(9) 4. 5. 6. 7. 8. 9.