二,数据传送指令存储器
I/O
接口输入设备
I/O
接口数据总线 DB
控制总线 CB
地址总线 AB
输入设备CPU
寄存器,存储器,I/O端口
▲ 数据传送是最基本,最重要的一种操作实际程序中,使用的比例最高
change PROC
LEA SI,num+2
MOV CL,num+1
MOV CH,0
MOV AX,0
MOV DI,10
next,MUL DI
MOV BH,0
MOV BL,[SI]
AND BL,0FH
ADD AX,BX
INC SI
LOOP next
zero,MOV BX,AX
RET
change ENDP
汇编子程例,
寄存器 寄存器寄存器 内存单元寄存器 I/O端口设臵寄存器,内存单元的初始值
▲ 按传送内容,可分为四类:
1,通用数据传送 MOV,PUSH,POP,XCHG,XLAT
2,地址传送 LEA,LDS,LES
3,标志传送 PUSHF,POPF,LAHF,SAHF
4,输入输出传送 IN,OUT (在第五章介绍 )
▲ 特点:
1,除 POPF,SAHF外,其他传送指令对标志位均无影响
2,唯一允许以段寄存器做操作数的指令且只有 MOV,PUSH,POP这三条允许
1,通用传送指令 MOV,PUSH,POP,XCHG,XLAT
reg/mem/segreg ← reg
reg/segreg ← mem
reg/mem ← segreg
reg/mem ← data
可实现
1) MOV传送指令格式 MOV dst,src
执行 ( dst ) ← ( src )
例,
① reg/mem/segreg ← reg 通用寄存器 /存储器 /段寄存器 ← 通用寄存器
MOV AL,BL
MOV [ BX ],AL
MOV DS,AX
② reg/segreg ← mem 通用寄存器 /段寄存器 ← 存储器
MOV AL,[ BX ]
MOV DS,[ BX+SI ]
③ reg/mem ← segreg 通用寄存器 /存储器 ← 段寄存器
MOV BX,CS
MOV [ BX ],DS
④ reg/mem ← data 通用寄存器 /存储器 ← 立即数
MOV Al,9
MOV BX,OFFSET buffer
MOV [ value ],0
MOV WORD PTR [ BX ],1
MOV指令特点及注意事项,
双操作数指令 (注意双操作指令的特点 )
可进行字节或字传送
不允许存储器传送到存储器
MOV [ BX ],value
MOV [DI],[SI]
MOV AX,value
MOV [ BX ],AX
MOV AL,[SI]
MOV [ DI ],AL
可对 DS,ES,SS 赋值但 不允许立即数直接传送给段寄存器
MOV DS,AX
MOV ES,[BX]
MOV DS,1000H
MOV AX,1000H
MOV DS,AX
CS不能做目的操作数,不能通过传送指令改变 CS的值
MOV CS,AX
不允许段寄存器传送到段寄存器
MOV ES,DS
MOV AX,DS
MOV ES,AX
D:\MASM>DEBUG
-A
1693:0100 MOV ES,DS
^ Error
1693:0100 MOV AX,DS
1693:0102 MOV ES,AX
1693:0104
-
2) PUSH入栈操作格式 PUSH src
执行 ( SP) ← ( SP) -2
( SS,SP) ← ( src)
特点,
单操作数指令
操作数为 16位,可以是 reg/segreg/mem,不可以是 data
reg,AX,BX,CX,DX,SI,DI,BP,BX
segreg,CS,DS,ES,SS
mem,字类型
SS:SP
SS:SP (src)
例,PUSH AX
若执行前:
( SS) = 2000H
( SP) = 1002H
( SS,SP) = 2010H
( AX) = 1234H
3B
2A
10
低高
20
地址
SS:SP
2000:1002
指令执行前
(AX)=1234h
则执行后:
( SS) = 2000H
( SP) = 1000H
( SS,SP) = 1234H
( AX) = 1234H
12
34
10
低高
20
地址
SS:SP
2000:1000
指令执行后
(AX)=1234h
不变减 2
变不变
D:\MASM>DEBUG
-A ;汇编两条指令
1693:0100 MOV AX,1234
1693:0103 PUSH AX
1693:0104
-R ;显示指令执行前寄存器值
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0100 NV UP EI PL NZ NA PO NC
1693:0100 B83412 MOV AX,1234
-T=100 2 ;执行 CS:100开始处的两条指令
….
AX=1234 BX=0000 CX=0000 DX=0000 SP=FFEC BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0104 NV UP EI PL NZ NA PO NC
1693:0104 03C6 ADD AX,SI
-D SS:FFEC L10 ;查看栈顶内容
1693:FFE0 34 12 00 00 4...
1693:FFF0 FF FF FF FF FF FF FF FF-FF FF FF FF,...........
-Q
例 利用 DEBUG学习 PUSH指令注意相关寄存器和内存单元内容的变化
3) POP出栈操作特点,
单操作数指令
操作数为 16位,可以是 reg/segreg/mem,不可以是 data
reg,AX,BX,CX,DX,SI,DI,BP,BX
segreg,DS,ES,SS,不允许是 CS
mem,字类型
SS:SP
SS:SP (dst)
格式 POP dst
执行 ( dst) ← ( SS,SP)
( SP) ← ( SP) + 2
若执行前:
( SS) = 2000H
( SP) = 1000H
( SS,SP) = 1234H
( BX) = 5678H
12
34
10
低高20
SS:SP
2000:1000
指令执行前地址
(BX)=5678h
例,POP BX
12
34
10
低高20
SS:SP
2000:1002
指令执行后地址
(BX)=1234h
则执行后:
( SS) = 2000H
( SP) = 1002H
( SS,SP) = 2010H
( BX) = 1234H
不变加 2
变变
-A
1693:0100 MOV BP,SP ;取当前栈顶地址
1693:0102 MOV WORD PTR [BP],1234 ;用 MOV指令使栈顶内容为 1234H
1693:0107 POP BX ;出栈指令
1693:0108
-R ;查看指令执行前状态
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0100 NV UP EI PL NZ NA PO NC
1693:0100 89E5 MOV BP,SP
-T=100 ;执行 CS:100处的第一条 mov指令
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0102 NV UP EI PL NZ NA PO NC
1693:0102 C746003412 MOV WORD PTR [BP+00],1234 SS:FFEE=0000
-T ;执行下一条 mov指令
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0107 NV UP EI PL NZ NA PO NC
1693:0107 5B POP BX
-T ;执行 pop指令,注意 BX,SP的变化
AX=0000 BX=1234 CX=0000 DX=0000 SP=FFF0 BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0108 NV UP EI PL NZ NA PO NC
1693:0108 F5 CMC
-
例 在 DEBUG下学习 POP指令例,执行下列程序段
PUSH AX ①
PUSH BX ②
MOV AX,66H ③
MOV BX,99H ④
POP BX ⑤
POP AX ⑥
若执行前
( SS) = 3000H
( SP) = 200EH
( SS:SP) = 1234H
( AX) = 0A0BH
( BX) = 0C0DH
3000:200ESS:SP执行前
(AX)=0A0B (BX)=0C0D
34
12
执行 ① 后 3000:200CSS:SP 0B
0A
3000:200ASS:SP执行 ② 后 0D0C
3000:200CSS:SP
执行 ⑤ 后,(BX)=0C0D
执行 ③④ 后 (AX)=0066 (BX)=0099执行 ③④ 后
② 后执行 ⑥ 后,(AX)=0A0B
3000:200ESS:SP
( )
后用 PUSH往 SS段传送一批数据后,再用 POP取出时,
取出单元的顺序与存放时的顺序正好相反,,后进先出,
⑥ POPAX (AX)=0A0B
① PUSH AX
3000:200ESS:SP执行前
3000:200CSS:SP
3000:200ASS:SP② PUSH BX
3000:200ESS:SP
3000:200CSS:SP
0D
0C
0B
0A
34
12
⑤ POP BX (BX)=0C0D
(AX)=0A0B (BX)=0C0D
④ MOVAX,0066 (BX)=0099
③ MOVAX,0066 (AX)=0066
堆栈是一个内存区域 。
通常用于存放一些重要数据,
如程序的地址,或是需要恢复的数据 。 SS:SP
为方便数据的存放和恢复,
设臵专门的指针,指向堆栈中要操作的单元 。
段值由 SS 给出,偏移地址由 SP 给出
SS → 堆栈段寄存器 (stack segment)
SP → 堆栈指针寄存器 (stack point)
堆栈的概念 stack
堆栈操作指令 PUSH 和 POP,
对 SS 和 SP 指向的内存单元,
以,后进先出,方式进行操作 。
PUSH → 入栈操作 SP减小
POP → 出栈操作 SP增加
SP 指向栈顶,即堆栈的顶部,
编程员通过设臵堆栈区域,
利用堆栈操作,可方便的进行数据的存放和恢复 。
SS:SP
SS:0000
SS:FFFF
堆栈未用空间堆栈使用的场合
用堆栈保存恢复信息
(如上例 )
子程序的调用,返回以及中断调用,返回
( 控制转移指令中介绍 )
用堆栈传送数据
( 程序设计中介绍 )
注意事项
堆栈是一重要数据结构,使用堆栈应有明确目的 。
不乱用堆栈操作,不乱修改堆栈内容 。
PUSH,POP,PUSHF,POPF、
CALL,RET,INT,IRET
乱修改 SS 和 SP 的内容包括 乱用 BP参与的存储器操作数乱用指令
PUSH和 POP指令只能对字操作 。
PUSH AL
POP BYTE PTR [BX]
可以对段寄存器操作但 POP不能对 CS操作
PUSH DS
PUSH CS
POP ES
POP CS
4) XCHG交换指令格式 XCHG oprd1,oprd2
执行 (oprd1) (oprd2)
reg reg
reg mem
mem reg
可实现例 XCHG AX,BX 字操作执行前 ( AX) = 1122H ( BX) = 3344H
执行后 ( AX) = 3344H ( BX) = 1122H
例 XCHG AH,BL 字节操作执行前 ( AX) = 1122H ( BX) = 3344H
执行后 ( AX) = 4422H ( BX) = 3311H
XCHG oprd1,oprd2
注意事项,
双操作数指令
可 进行 字或字节操作
不允许对立即数,段寄存器做操作数
XCHG AX,4
XCHG BX,DS
2,地址传送指令 LEA,LDS,LES
LEA有效地址传送格式 LEA reg,mem
执行 ( reg) ← mem的 EA
即 寄存器 ← 存储器操作数的偏移地址执行后 ( BX ) = 1000H
注意:
OFFSET是汇编程序提供的一个操作符,不是 CPU的指令
LEA BX,buffer
例 buffer是一个符号地址表示的内存操作数 (变量 )。
…...
12h
34h
56h
…...
buffer
内存
DS,1000h若变量 buffer的偏移地址 = 1000H
等价于 MOV BX,OFFSET buffer
buffer 1A
2B
3C
4D
、、、
、、、
例 将 buffer为首的 4个字节内存内容相加,存放在 AL中 。
MOV AX,SEG buffer
MOV DS,AX
LEA BX,buffer
MOV CX,4
MOV AL,0
exit,ADD AL,[BX]
INC BX
DEC CX ;(cx) =(cx) -1
JNZ exit ;ZF ≠ 0,转至 exit
说明,1) 操作符 SEG 的作用是 取变量的段地址 。
执行完前两条指令后,(DS)=buffer的段值
2) 操作符 OFFSET的作用是 取变量的偏移地址执行完 LEA BX,buffer,(BX)为 buffer的偏移地址,
3)操作数 [BX]是以 DS为段值,BX为偏移值的内存单元
LEA reg,mem
特点及注意事项:
目的操作数 reg应是 16位通用寄存器
LEA ES,[BX]
LEA AL,buffer
LEA 6,[BX+SI]
LEA [DI],buffer
源操作数应是存储器操作数
LEA BX,AX
传送的是内存单元的有效地址,与其内容无关 。
…...
12h
34h
56h
…...
buffer
内存
3,标志传送 PUSHF,POPF,LAHF,SAHF
SS:SP
SS:SP (PSW)
2) POPF标志出栈格式 POPF
执行 ( PSW) ← ( SS,SP)
( SP) ← ( SP) + 2
SS:SP
SS:SP (PSW)
1) PUSHF标志入栈格式 PUSHF
执行 ( SP) ← ( SP) -2
( SS,SP) ← ( PSW)
特点及注意事项:
无操作数的形式,操作数隐含为 ( PSW)
PUSHF AX
POPF CX
PUSHF和 POPF用于标志信息的保存和恢复三,算术运算指令二进制运算 十进制调整加 ADD,A DC,IN C AAA,D AA
减 SUB,SB B,DEC,NE G,CM P AAS,D AS
乘 MU L,IMUL AAM
除 DIV,ID IV AAD
符号扩展指令,CBW,CWD
指令分类,
特点:
带符号数用补码表示如 MOV AX,-1 等价于 MOV AX,0FFFFh
对加,减运算,不区分无符号数,带符号数 (参见第一章例 )
对乘,除运算,区分无符号数,带符号数
可进行字节或字操作
影响状态标志
十进制运算方法 (不做重点,讲义中做了简单介绍 )
当数据用压缩或非压缩 BCD码表示时,
为使运算的结果仍为 BCD码表示,需对结果进行调整。
十进制运算 = 二进制运算 + 十进制调整十进制数码 0 1 2 3 4
8421 BC D 码 0000 0001 0010 001 1 0100
十进制数码 5 6 7 8 9
8421 BC D 码 0101 01 10 01 1 1 1000 1001
BCD码 ( Binary Coded Decimal )
用二进制编码表示十进制数 。
常用 8421 BCD码,与十进制数码对应关系:
例 48的 BCD码为 ( 0100 1000) BCD
根据在内存的存放形式,分压缩 BCD码和非压缩 BCD码
1) 压缩 BCD码一字节存放 2个 BCD码 。
如 2148 的压缩 BCD码为:
( 0010 0001 0100 1000 )压缩 BCD
在内存中占 2字节
2) 非压缩 BCD码一字节存放 1个 BCD码 。
如 2148 的非压缩 BCD码为:
( 00000010 00000001 00000100 00001000 ) 非压缩 BCD
在内存中占 4字节当数据用压缩或非压缩 BCD码表示时,
为使运算的结果仍为 BCD码表示,需对结果进行调整 。
十进制运算 = 二进制运算 + 十进制调整例 (0000 1000 )压缩 BCD + (0000 1001)压缩 BCD
= (0001 0111 ) 压缩 BCD
计算机计算过程 看作压缩 BCD
0000 1000 08
+ 0000 1001 09
0001 0001 11
二进制运算十进制调整 + 0000 0110
0001 0111 17
1,加法运算指令指令格式 执 行 操 作
ADD d st,sr c (dst ) ← (dst ) + (sr c )
ADC d st,sr c (dst ) ← (dst ) + (sr c ) + CF
INC op rd (op rd ) ← (op rd ) + 1
ADD,ADC为双操作数指令
INC为单操作数指令
除 INC指令不影响 CF外,6个状态标志均据结果设臵
ADC带进位加法,实现字以上运算
OF DF IF TF SF ZF AF PF CF
CFA1H 1100 1111 1010 0001
+ 62A0H + 0110 0010 1010 0000
111 1 1 1 1111 1
3241H 0011 0010 0100 0001
例 1 编程完成 CFA1H + 62A0H ( 做过的 随堂作业 )
MOV DX,0CFA1H
ADD DX,62A0H
执行后,
( DX) =3241H CF=1,OF=0,SF=0,ZF=0
( 注意 CF和 OF的判断方法 )
D:\MASM> DEBUG
-A ;汇编指令
1270:0100 MOV AX,CFA1
1270:0103 ADD AX,62A0
1270:0106
-R ;执行前查看各寄存器内容
AX=0000 BX=0000 CX=0000 DX=0000
SP=FFEE BP=0000 SI=0000 DI=0000
DS=1270 ES=1270 SS=1270 CS=1270 IP=0100 NV UP EI PL NZ NA PO NC
1270:0100 B8A1CF MOV AX,CFA1
-T 2 ;执行汇编的两条指令,并查看执行后的结果
…...
AX=3241 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000
DI=0000
DS=1270 ES=1270 SS=1270 CS=1270 IP=0106 NV UP EI PL NZ NA PE CY
1270:0106 57 PUSH DI
-
利用 DEBUG学习加法指令三组指令执行后的结果均为,
(AL)=0FDH,CF=0,OF=0,SF=1,ZF=0
MOV AL,0F1H
ADD AL,0CH
MOV AL,241
ADD AL,12
MOV AL,-15
ADD AL,12
第一章中的例题
F1 H
+ 0C H
FD H
二进制运 算
241
+ 12
253
看 作无符号数
(-15)
+ 12
(-3)
看 作带符号数
B0
F1
04
0C
、、、
、、、
第一条指 令第二条指 令三组机器码相同:
对加,减运算,CPU计算时不区分无符号数,带符号数例 2 INC AL
执行前 ( AL) = FFH
执行后,
( AL) =00H
CF=不变,OF=0,ZF=1,SF=0
FFH
+ 01H
11
00H
01FFH
+ 0001H
11
0200H
例 3 value 是一个字变量
OFFSET value = 1000H
( DS) =2000H,( 21000H) =01FFH
value FF
21000H 01
执行前
value 00
21000H 02
执行后执行后:
( 21000H) =0200H
CF=不变,OF=0,ZF=0,SF=0
注意是内存单元内容加 1,而非地址加 1
INC value
或写成,
INC [value]
例 4 将 buffer为首的 4个字节内存内容相加,存放在 AL中 。
buffer 1A
B7
C5
D6
若编程如下,
MOV CX,4
MOV AL,0
exit,ADD AL,[buffer]
INC buffer
DEC CX
JNZ exit
不能实现,为什么?
…,..
MOV CX,4
LEA BX,buffer
MOV AL,0
exit,ADD AL,[BX]
INC BX
DEC CX
JNZ exit
实现的是 1A+1B+1C+1D
指令 INC buffer
将 buffer指向的内容加 1,
而不是地址 buffer加 1
例 5 两双字相加 0002F365H + 0005 E024 H =?
MOV AX,0F365H ①
ADD AX,0E024H ②
MOV BX,0002H ③
ADC BX,0005H ④
0002 F365 H
+ 0005 E024 H
1
0008 D389 H
结果存放在,0008 D389
( BX) ( AX)
执行完 ①,②,(AX)= D389H CF=1,OF=0,SF=1,ZF=0
执行完 ③,④,(BX)= 0008H CF=0,OF=0,SF=0,ZF=0
分析,8086/8088只能按字节或字相加 。
位数在字以上的操作数,先加低位,再加高位,
加高位时加入从低位产生的进位 。
指令格式 执行操作
SUB dst,sr c (dst ) ← (dst ) - (sr c )
SB B dst,sr c (dst ) ← (dst ) - (sr c ) - CF
DE C opr d (op rd ) ← (op rd ) - 1
NE G opr d (op rd ) ← 0 - (op r d )
CM P opr d1,op rd 2 (op rd 1) - (op rd 2)
2,减法运算指令
SUB,SBB,CMP为双操作数,DEC,NEG为单操作数
SBB为带进位减法
除 DEC不影响 CF标志外,6个状态标志均据结果臵位
NEG求补运算,等价于用 0减去操作数 。
其对标志位的影响,由 0减去该操作数的过程决定 。
例 1 编程完成 2D04H – 3AB0H
执行后,
( AX) =0F254H CF=1,OF=0,SF=1,ZF=0
2D04H 0010 1101 0000 0100
- 3AB0H - 0011 1010 1011 0000
1 1 1111 1 1 111
F254H 1111 0010 0101 0100
MOV AX,2D04H
SUB AX,3AB0H
借位例 2 value 是一个字节变量
OFFSET value = 1000H
( DS) =2000H,( 21000H) =00H
DEC value
执行后,( 21000H) =0FFH
CF=不变,OF=0,ZF=0,SF=1
注意是内存单元内容减 1,而非地址减 1
00 H
- 01 H
11
FFH
例 3 MOV AH,80H
NEG AH
00 H 0000 0000 B
- 80 H - 1000 0000 B
1 1
80H 1000 0000B
执行后:
( AL) =80H CF=1,OF=1,ZF=0,SF=1
例 4 用指令完成两双字相减运算
0546 7A70H
- F001 A543H
MOV AX,7A70H
SUB AX,A543H
MOV BX,0546H
SBB BX,0F001H
CMP oprd1,oprd2 ; (oprd1) - (oprd2)
① 据 ZF判断两数是否相等
CMP A,B
ZF=1 两数相等,A = B;
ZF=0 两数不等,A ≠ B
② 据 ZF和 CF判断两无符号数关系
CF= 1 A低于 B
CF= 0 A高于等于 B
CF=1或 ZF=1 A低于等于 B
CF=0且 ZF=0 A高于 B
利用 CMP执行后的标志值,比较两操作数之间的关系
比较指令 CMP,进行两操作数相减操作,
但只影响标志值,不影响操作数 (减的结果不保存 )
条件转移指令 判断条件低于 JB ne xt CF = 1
低于等于 JB E ne xt CF = 1 或 Z F = 1
高于 JA ne xt CF = 0 且 Z F = 0
高于等于 JA E ne xt CF = 0
CMP AX,BX ;比较
JAE above ;高于等于则跳转
XCHG AX,BX ;低于则交换
above:,、、
例 将 AX和 BX中较大的无符号数,存于 AX中
CMP A,B
③ 用 ZF,SF和 OF判断两带符号数关系
OF=0,不溢出情况,
SF=0,A≥B
SF=1,A< B
OF=0,SF=0 A≥B
OF=0,SF=1 A< B
OF=1,SF=1 A> B
OF=1,SF=0 A< B
0
- 1 正 - 负 = 负,结果 SF = 1,OF=1
1 但,正 > 负,知 A> B
1
- 0 负 - 正 = 正,结果 SF = 0,OF=1
0 但,负 < 正,知 A< B
OF=1,溢出情况,
(由符号位可决定是否溢出 )
结合 ZF,得到结论,
SF
OF
0
0
0
1
1
0
1
1
SF ∨ OF 0 1 1 1
或运算,有 1 则 1,全 0 则 0
逻辑运算:
CM P A,B 两数关系
SF ∨ O F = 0 A ≥ B
SF ∨ O F = 1 A < B
( SF ∨ OF ) ∨ ZF = 0 A > B
( SF ∨ OF ) ∨ Z F = 1 A ≤ B思考:可否只用 ZF 和 SF
判断两符号数关系?
SF
OF
0
0
0
1 0
1
1
SF ∨ OF 0 1 0
异或运算,异则 1,同则 0
条件转移指令 判断条件小于 JL nex t SF ∨ O F = 1
小于等于 J L E nex t ( SF ∨ OF ) ∨ ZF =1
大于 J G next ( SF ∨ OF ) ∨ ZF = 0
大于等于 J G E next SF ∨ O F= 0
例 将 AX和 BX中较大的带符号数,存于 AX中
CMP AX,BX ;比较
JGE great ;大于等于则跳转
XCHG AX,BX ;小于则交换
great:,、、
3,乘法指令指令格式 执行操作
M UL sr c
若 sr c 为字节类型:
( AX ) ← ( AL ) × (sr c )
若 sr c 为字类型:
( DX ),( AX ) ← ( AX ) × (sr c )
将被乘数、乘数看作无符号数,进行乘运算乘的结果也为无带符号数
I M UL sr c
执行的操作与 M U L 相似将被乘数、乘数看作带符号数,进行乘运算乘的结果也为带符号数无符号数乘法带符号数乘法
MUL src
IMUL src
单操作数指令
源操作数 ( 乘数 )类型决定操作类型
目的操作数 (被乘数 ) 隐含 。
字节乘 AL 字乘 AX
字节相乘的结果存放在 AX中字相乘的结果存放在 DX,AX中
MUL 用于无符号数运算
IMUL 用于带符号数运算
影响 CF和 OF,对其他条件码 无定义 ( 不确定 )
指令 MUL
字节相乘,AH=0,CF=OF=0,否则 CF=OF=1
字相乘,DX=0,CF=OF=0,否则 CF=OF=1
对指令 IMUL
字节相乘,AH=0或 AH=FFH,CF=OF=0,否则 CF=OF=1
字相乘,DX=0或 DX=FFFFH,CF=OF=0,否则 CF=OF=1
例 (AL) = 0B4H,(BL) = 11H
指令中源操作数为字节类型,故是字节操作
① MUL BL ② IMUL BL
看作无符号数
(AL) = 180D
(BL) = 17D
180× 17 = 3060D
= 0BF4H
执行 MUL BL后:
(AX) = 0BF4H
看作带符号数
(AL) = -76D
(BL) =17D
(-76)× 17 = -1292D
= 0FAF4H
执行 IMUL BL后:
(AX) = 0FAF4H
例 (AX)=0FFFFH,(BX)=0FFFFH
指令中源操作数为字类型,故是字操作
① MUL BX
执行 MUL BX后:
(DX) = 0FFFEH
(AX) = 0001H
看作无符号数
(AX )= (BX) = 65535
65535× 65535
= 4294836225
= 0FFFE 0001H
② IMUL BX
看作带符号数
(AX)= (BX)=-1
(-1)× (-1)
= 1
= 0000 0001H
执行 IMUL BX后:
(DX) = 0000H
(AX) = 0001H
4,除法指令指令格式 执行操作
D IV sr c
无符号数除法
(sr c) 为字节类型:
( A L) ← ( A X) / (s r c) 的商
( AH ) ← ( A X) / (sr c) 的余数
(sr c) 为字类型:
( AX ) ← D X ),( AX ) / (sr c) 的商
(DX) ← (DX ),( A X) / (sr c ) 的余数将被除数、除数看作无符号数,进行除法运算,
商、余数也为无符号数
ID IV sr c
带符号数除法执行的操作与 D IV 相同,
将被除数、除数看作带符号数,进行除法晕眩商、余数也为带符号数,余数的符号与被除数同
单操作数指令
源操作数 (除数 )类型 决定指令操作类型
目的操作数 (被除数 )隐含字节操作在 AX中;字操作在 DX,AX中
除的结果,字节操作在 AX中;字操作在 DX,AX中
除法指令对所有条件码位均 无定义
下列情况自动转入 0 中断处理:
(1) 除数为 0
(2) 字节操作,商的范围超出字节范围字操作时,商的范围超出字范围除法指令举例例 (AX)=0501H,(BL)=0C6H
(1) DIV BL (2) IDIV BL
看作无符号数 看作带符号数
(AL) = 1281D (AL) = 1281D
(BL) = 198D (BL) = -58D
1281/198商 = 6D 1281/ (-58)商 = -22D=0EAH
余数 =93D=5DH 余数 =5D
执行 DIV BL后,执行 IDIV BL后:
(AX) = 5D06H (AX) = 05EAH
5,符号扩展指令指令格式 执行操作
CBW
将 ( AL ) 的符号扩展到 AH 中
( AL ) 的 D7=0,( AH ) =0 0H
D 7 = 1,( AH ) =FFH
CWD
将 ( AX ) 的符号扩展到 D X 中
(AX ) 的 D15 =0,( DX ) =0 00 0 H
D 1 5 = 1,( DX ) =FFF FH
无操作数格式
操作数隐含字节操作,源在 AL,目的在 AX
字 操 作,源在 AX,目的在 DX,AX
对条件码无影响
符号扩展指令应对带符号数操作
扩展后,表示的数值大小不变,只是位数发生变化
8位 16位 16位 32位
应用场合:
除法指令中,使被除数满足要求 。
字节操作,被除数为 16位字操作,被除数为 32位加减运算中,使两操作数类型一致如:字与字节相加,减时如:双字与字之间的相加,减时符号扩展指令举例例 CBW
执行前 (AL)=01H,(AH)=0FFH
执行后 (AL)=01H,(AH)=00H
例 CWD
执行前 (AX)=0FF00H,(DX)=0011H
执行后 (AX)=0FF00H,(DX)=0FFFFH
例 ( AL) =0FFH,将其内容扩展至 (AX)中看作无符号数为 255,
若用 MOV AH,0H
(AX)=00FFH=255D
若用 CBW
(AX)=0FFFFH=65535≠原数故,对无符号数的扩展不能用符号扩展指令对无符号数的扩展,直接给高位赋 0。
I/O
接口输入设备
I/O
接口数据总线 DB
控制总线 CB
地址总线 AB
输入设备CPU
寄存器,存储器,I/O端口
▲ 数据传送是最基本,最重要的一种操作实际程序中,使用的比例最高
change PROC
LEA SI,num+2
MOV CL,num+1
MOV CH,0
MOV AX,0
MOV DI,10
next,MUL DI
MOV BH,0
MOV BL,[SI]
AND BL,0FH
ADD AX,BX
INC SI
LOOP next
zero,MOV BX,AX
RET
change ENDP
汇编子程例,
寄存器 寄存器寄存器 内存单元寄存器 I/O端口设臵寄存器,内存单元的初始值
▲ 按传送内容,可分为四类:
1,通用数据传送 MOV,PUSH,POP,XCHG,XLAT
2,地址传送 LEA,LDS,LES
3,标志传送 PUSHF,POPF,LAHF,SAHF
4,输入输出传送 IN,OUT (在第五章介绍 )
▲ 特点:
1,除 POPF,SAHF外,其他传送指令对标志位均无影响
2,唯一允许以段寄存器做操作数的指令且只有 MOV,PUSH,POP这三条允许
1,通用传送指令 MOV,PUSH,POP,XCHG,XLAT
reg/mem/segreg ← reg
reg/segreg ← mem
reg/mem ← segreg
reg/mem ← data
可实现
1) MOV传送指令格式 MOV dst,src
执行 ( dst ) ← ( src )
例,
① reg/mem/segreg ← reg 通用寄存器 /存储器 /段寄存器 ← 通用寄存器
MOV AL,BL
MOV [ BX ],AL
MOV DS,AX
② reg/segreg ← mem 通用寄存器 /段寄存器 ← 存储器
MOV AL,[ BX ]
MOV DS,[ BX+SI ]
③ reg/mem ← segreg 通用寄存器 /存储器 ← 段寄存器
MOV BX,CS
MOV [ BX ],DS
④ reg/mem ← data 通用寄存器 /存储器 ← 立即数
MOV Al,9
MOV BX,OFFSET buffer
MOV [ value ],0
MOV WORD PTR [ BX ],1
MOV指令特点及注意事项,
双操作数指令 (注意双操作指令的特点 )
可进行字节或字传送
不允许存储器传送到存储器
MOV [ BX ],value
MOV [DI],[SI]
MOV AX,value
MOV [ BX ],AX
MOV AL,[SI]
MOV [ DI ],AL
可对 DS,ES,SS 赋值但 不允许立即数直接传送给段寄存器
MOV DS,AX
MOV ES,[BX]
MOV DS,1000H
MOV AX,1000H
MOV DS,AX
CS不能做目的操作数,不能通过传送指令改变 CS的值
MOV CS,AX
不允许段寄存器传送到段寄存器
MOV ES,DS
MOV AX,DS
MOV ES,AX
D:\MASM>DEBUG
-A
1693:0100 MOV ES,DS
^ Error
1693:0100 MOV AX,DS
1693:0102 MOV ES,AX
1693:0104
-
2) PUSH入栈操作格式 PUSH src
执行 ( SP) ← ( SP) -2
( SS,SP) ← ( src)
特点,
单操作数指令
操作数为 16位,可以是 reg/segreg/mem,不可以是 data
reg,AX,BX,CX,DX,SI,DI,BP,BX
segreg,CS,DS,ES,SS
mem,字类型
SS:SP
SS:SP (src)
例,PUSH AX
若执行前:
( SS) = 2000H
( SP) = 1002H
( SS,SP) = 2010H
( AX) = 1234H
3B
2A
10
低高
20
地址
SS:SP
2000:1002
指令执行前
(AX)=1234h
则执行后:
( SS) = 2000H
( SP) = 1000H
( SS,SP) = 1234H
( AX) = 1234H
12
34
10
低高
20
地址
SS:SP
2000:1000
指令执行后
(AX)=1234h
不变减 2
变不变
D:\MASM>DEBUG
-A ;汇编两条指令
1693:0100 MOV AX,1234
1693:0103 PUSH AX
1693:0104
-R ;显示指令执行前寄存器值
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0100 NV UP EI PL NZ NA PO NC
1693:0100 B83412 MOV AX,1234
-T=100 2 ;执行 CS:100开始处的两条指令
….
AX=1234 BX=0000 CX=0000 DX=0000 SP=FFEC BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0104 NV UP EI PL NZ NA PO NC
1693:0104 03C6 ADD AX,SI
-D SS:FFEC L10 ;查看栈顶内容
1693:FFE0 34 12 00 00 4...
1693:FFF0 FF FF FF FF FF FF FF FF-FF FF FF FF,...........
-Q
例 利用 DEBUG学习 PUSH指令注意相关寄存器和内存单元内容的变化
3) POP出栈操作特点,
单操作数指令
操作数为 16位,可以是 reg/segreg/mem,不可以是 data
reg,AX,BX,CX,DX,SI,DI,BP,BX
segreg,DS,ES,SS,不允许是 CS
mem,字类型
SS:SP
SS:SP (dst)
格式 POP dst
执行 ( dst) ← ( SS,SP)
( SP) ← ( SP) + 2
若执行前:
( SS) = 2000H
( SP) = 1000H
( SS,SP) = 1234H
( BX) = 5678H
12
34
10
低高20
SS:SP
2000:1000
指令执行前地址
(BX)=5678h
例,POP BX
12
34
10
低高20
SS:SP
2000:1002
指令执行后地址
(BX)=1234h
则执行后:
( SS) = 2000H
( SP) = 1002H
( SS,SP) = 2010H
( BX) = 1234H
不变加 2
变变
-A
1693:0100 MOV BP,SP ;取当前栈顶地址
1693:0102 MOV WORD PTR [BP],1234 ;用 MOV指令使栈顶内容为 1234H
1693:0107 POP BX ;出栈指令
1693:0108
-R ;查看指令执行前状态
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0100 NV UP EI PL NZ NA PO NC
1693:0100 89E5 MOV BP,SP
-T=100 ;执行 CS:100处的第一条 mov指令
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0102 NV UP EI PL NZ NA PO NC
1693:0102 C746003412 MOV WORD PTR [BP+00],1234 SS:FFEE=0000
-T ;执行下一条 mov指令
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0107 NV UP EI PL NZ NA PO NC
1693:0107 5B POP BX
-T ;执行 pop指令,注意 BX,SP的变化
AX=0000 BX=1234 CX=0000 DX=0000 SP=FFF0 BP=FFEE SI=0000 DI=0000
DS=1693 ES=1693 SS=1693 CS=1693 IP=0108 NV UP EI PL NZ NA PO NC
1693:0108 F5 CMC
-
例 在 DEBUG下学习 POP指令例,执行下列程序段
PUSH AX ①
PUSH BX ②
MOV AX,66H ③
MOV BX,99H ④
POP BX ⑤
POP AX ⑥
若执行前
( SS) = 3000H
( SP) = 200EH
( SS:SP) = 1234H
( AX) = 0A0BH
( BX) = 0C0DH
3000:200ESS:SP执行前
(AX)=0A0B (BX)=0C0D
34
12
执行 ① 后 3000:200CSS:SP 0B
0A
3000:200ASS:SP执行 ② 后 0D0C
3000:200CSS:SP
执行 ⑤ 后,(BX)=0C0D
执行 ③④ 后 (AX)=0066 (BX)=0099执行 ③④ 后
② 后执行 ⑥ 后,(AX)=0A0B
3000:200ESS:SP
( )
后用 PUSH往 SS段传送一批数据后,再用 POP取出时,
取出单元的顺序与存放时的顺序正好相反,,后进先出,
⑥ POPAX (AX)=0A0B
① PUSH AX
3000:200ESS:SP执行前
3000:200CSS:SP
3000:200ASS:SP② PUSH BX
3000:200ESS:SP
3000:200CSS:SP
0D
0C
0B
0A
34
12
⑤ POP BX (BX)=0C0D
(AX)=0A0B (BX)=0C0D
④ MOVAX,0066 (BX)=0099
③ MOVAX,0066 (AX)=0066
堆栈是一个内存区域 。
通常用于存放一些重要数据,
如程序的地址,或是需要恢复的数据 。 SS:SP
为方便数据的存放和恢复,
设臵专门的指针,指向堆栈中要操作的单元 。
段值由 SS 给出,偏移地址由 SP 给出
SS → 堆栈段寄存器 (stack segment)
SP → 堆栈指针寄存器 (stack point)
堆栈的概念 stack
堆栈操作指令 PUSH 和 POP,
对 SS 和 SP 指向的内存单元,
以,后进先出,方式进行操作 。
PUSH → 入栈操作 SP减小
POP → 出栈操作 SP增加
SP 指向栈顶,即堆栈的顶部,
编程员通过设臵堆栈区域,
利用堆栈操作,可方便的进行数据的存放和恢复 。
SS:SP
SS:0000
SS:FFFF
堆栈未用空间堆栈使用的场合
用堆栈保存恢复信息
(如上例 )
子程序的调用,返回以及中断调用,返回
( 控制转移指令中介绍 )
用堆栈传送数据
( 程序设计中介绍 )
注意事项
堆栈是一重要数据结构,使用堆栈应有明确目的 。
不乱用堆栈操作,不乱修改堆栈内容 。
PUSH,POP,PUSHF,POPF、
CALL,RET,INT,IRET
乱修改 SS 和 SP 的内容包括 乱用 BP参与的存储器操作数乱用指令
PUSH和 POP指令只能对字操作 。
PUSH AL
POP BYTE PTR [BX]
可以对段寄存器操作但 POP不能对 CS操作
PUSH DS
PUSH CS
POP ES
POP CS
4) XCHG交换指令格式 XCHG oprd1,oprd2
执行 (oprd1) (oprd2)
reg reg
reg mem
mem reg
可实现例 XCHG AX,BX 字操作执行前 ( AX) = 1122H ( BX) = 3344H
执行后 ( AX) = 3344H ( BX) = 1122H
例 XCHG AH,BL 字节操作执行前 ( AX) = 1122H ( BX) = 3344H
执行后 ( AX) = 4422H ( BX) = 3311H
XCHG oprd1,oprd2
注意事项,
双操作数指令
可 进行 字或字节操作
不允许对立即数,段寄存器做操作数
XCHG AX,4
XCHG BX,DS
2,地址传送指令 LEA,LDS,LES
LEA有效地址传送格式 LEA reg,mem
执行 ( reg) ← mem的 EA
即 寄存器 ← 存储器操作数的偏移地址执行后 ( BX ) = 1000H
注意:
OFFSET是汇编程序提供的一个操作符,不是 CPU的指令
LEA BX,buffer
例 buffer是一个符号地址表示的内存操作数 (变量 )。
…...
12h
34h
56h
…...
buffer
内存
DS,1000h若变量 buffer的偏移地址 = 1000H
等价于 MOV BX,OFFSET buffer
buffer 1A
2B
3C
4D
、、、
、、、
例 将 buffer为首的 4个字节内存内容相加,存放在 AL中 。
MOV AX,SEG buffer
MOV DS,AX
LEA BX,buffer
MOV CX,4
MOV AL,0
exit,ADD AL,[BX]
INC BX
DEC CX ;(cx) =(cx) -1
JNZ exit ;ZF ≠ 0,转至 exit
说明,1) 操作符 SEG 的作用是 取变量的段地址 。
执行完前两条指令后,(DS)=buffer的段值
2) 操作符 OFFSET的作用是 取变量的偏移地址执行完 LEA BX,buffer,(BX)为 buffer的偏移地址,
3)操作数 [BX]是以 DS为段值,BX为偏移值的内存单元
LEA reg,mem
特点及注意事项:
目的操作数 reg应是 16位通用寄存器
LEA ES,[BX]
LEA AL,buffer
LEA 6,[BX+SI]
LEA [DI],buffer
源操作数应是存储器操作数
LEA BX,AX
传送的是内存单元的有效地址,与其内容无关 。
…...
12h
34h
56h
…...
buffer
内存
3,标志传送 PUSHF,POPF,LAHF,SAHF
SS:SP
SS:SP (PSW)
2) POPF标志出栈格式 POPF
执行 ( PSW) ← ( SS,SP)
( SP) ← ( SP) + 2
SS:SP
SS:SP (PSW)
1) PUSHF标志入栈格式 PUSHF
执行 ( SP) ← ( SP) -2
( SS,SP) ← ( PSW)
特点及注意事项:
无操作数的形式,操作数隐含为 ( PSW)
PUSHF AX
POPF CX
PUSHF和 POPF用于标志信息的保存和恢复三,算术运算指令二进制运算 十进制调整加 ADD,A DC,IN C AAA,D AA
减 SUB,SB B,DEC,NE G,CM P AAS,D AS
乘 MU L,IMUL AAM
除 DIV,ID IV AAD
符号扩展指令,CBW,CWD
指令分类,
特点:
带符号数用补码表示如 MOV AX,-1 等价于 MOV AX,0FFFFh
对加,减运算,不区分无符号数,带符号数 (参见第一章例 )
对乘,除运算,区分无符号数,带符号数
可进行字节或字操作
影响状态标志
十进制运算方法 (不做重点,讲义中做了简单介绍 )
当数据用压缩或非压缩 BCD码表示时,
为使运算的结果仍为 BCD码表示,需对结果进行调整。
十进制运算 = 二进制运算 + 十进制调整十进制数码 0 1 2 3 4
8421 BC D 码 0000 0001 0010 001 1 0100
十进制数码 5 6 7 8 9
8421 BC D 码 0101 01 10 01 1 1 1000 1001
BCD码 ( Binary Coded Decimal )
用二进制编码表示十进制数 。
常用 8421 BCD码,与十进制数码对应关系:
例 48的 BCD码为 ( 0100 1000) BCD
根据在内存的存放形式,分压缩 BCD码和非压缩 BCD码
1) 压缩 BCD码一字节存放 2个 BCD码 。
如 2148 的压缩 BCD码为:
( 0010 0001 0100 1000 )压缩 BCD
在内存中占 2字节
2) 非压缩 BCD码一字节存放 1个 BCD码 。
如 2148 的非压缩 BCD码为:
( 00000010 00000001 00000100 00001000 ) 非压缩 BCD
在内存中占 4字节当数据用压缩或非压缩 BCD码表示时,
为使运算的结果仍为 BCD码表示,需对结果进行调整 。
十进制运算 = 二进制运算 + 十进制调整例 (0000 1000 )压缩 BCD + (0000 1001)压缩 BCD
= (0001 0111 ) 压缩 BCD
计算机计算过程 看作压缩 BCD
0000 1000 08
+ 0000 1001 09
0001 0001 11
二进制运算十进制调整 + 0000 0110
0001 0111 17
1,加法运算指令指令格式 执 行 操 作
ADD d st,sr c (dst ) ← (dst ) + (sr c )
ADC d st,sr c (dst ) ← (dst ) + (sr c ) + CF
INC op rd (op rd ) ← (op rd ) + 1
ADD,ADC为双操作数指令
INC为单操作数指令
除 INC指令不影响 CF外,6个状态标志均据结果设臵
ADC带进位加法,实现字以上运算
OF DF IF TF SF ZF AF PF CF
CFA1H 1100 1111 1010 0001
+ 62A0H + 0110 0010 1010 0000
111 1 1 1 1111 1
3241H 0011 0010 0100 0001
例 1 编程完成 CFA1H + 62A0H ( 做过的 随堂作业 )
MOV DX,0CFA1H
ADD DX,62A0H
执行后,
( DX) =3241H CF=1,OF=0,SF=0,ZF=0
( 注意 CF和 OF的判断方法 )
D:\MASM> DEBUG
-A ;汇编指令
1270:0100 MOV AX,CFA1
1270:0103 ADD AX,62A0
1270:0106
-R ;执行前查看各寄存器内容
AX=0000 BX=0000 CX=0000 DX=0000
SP=FFEE BP=0000 SI=0000 DI=0000
DS=1270 ES=1270 SS=1270 CS=1270 IP=0100 NV UP EI PL NZ NA PO NC
1270:0100 B8A1CF MOV AX,CFA1
-T 2 ;执行汇编的两条指令,并查看执行后的结果
…...
AX=3241 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000
DI=0000
DS=1270 ES=1270 SS=1270 CS=1270 IP=0106 NV UP EI PL NZ NA PE CY
1270:0106 57 PUSH DI
-
利用 DEBUG学习加法指令三组指令执行后的结果均为,
(AL)=0FDH,CF=0,OF=0,SF=1,ZF=0
MOV AL,0F1H
ADD AL,0CH
MOV AL,241
ADD AL,12
MOV AL,-15
ADD AL,12
第一章中的例题
F1 H
+ 0C H
FD H
二进制运 算
241
+ 12
253
看 作无符号数
(-15)
+ 12
(-3)
看 作带符号数
B0
F1
04
0C
、、、
、、、
第一条指 令第二条指 令三组机器码相同:
对加,减运算,CPU计算时不区分无符号数,带符号数例 2 INC AL
执行前 ( AL) = FFH
执行后,
( AL) =00H
CF=不变,OF=0,ZF=1,SF=0
FFH
+ 01H
11
00H
01FFH
+ 0001H
11
0200H
例 3 value 是一个字变量
OFFSET value = 1000H
( DS) =2000H,( 21000H) =01FFH
value FF
21000H 01
执行前
value 00
21000H 02
执行后执行后:
( 21000H) =0200H
CF=不变,OF=0,ZF=0,SF=0
注意是内存单元内容加 1,而非地址加 1
INC value
或写成,
INC [value]
例 4 将 buffer为首的 4个字节内存内容相加,存放在 AL中 。
buffer 1A
B7
C5
D6
若编程如下,
MOV CX,4
MOV AL,0
exit,ADD AL,[buffer]
INC buffer
DEC CX
JNZ exit
不能实现,为什么?
…,..
MOV CX,4
LEA BX,buffer
MOV AL,0
exit,ADD AL,[BX]
INC BX
DEC CX
JNZ exit
实现的是 1A+1B+1C+1D
指令 INC buffer
将 buffer指向的内容加 1,
而不是地址 buffer加 1
例 5 两双字相加 0002F365H + 0005 E024 H =?
MOV AX,0F365H ①
ADD AX,0E024H ②
MOV BX,0002H ③
ADC BX,0005H ④
0002 F365 H
+ 0005 E024 H
1
0008 D389 H
结果存放在,0008 D389
( BX) ( AX)
执行完 ①,②,(AX)= D389H CF=1,OF=0,SF=1,ZF=0
执行完 ③,④,(BX)= 0008H CF=0,OF=0,SF=0,ZF=0
分析,8086/8088只能按字节或字相加 。
位数在字以上的操作数,先加低位,再加高位,
加高位时加入从低位产生的进位 。
指令格式 执行操作
SUB dst,sr c (dst ) ← (dst ) - (sr c )
SB B dst,sr c (dst ) ← (dst ) - (sr c ) - CF
DE C opr d (op rd ) ← (op rd ) - 1
NE G opr d (op rd ) ← 0 - (op r d )
CM P opr d1,op rd 2 (op rd 1) - (op rd 2)
2,减法运算指令
SUB,SBB,CMP为双操作数,DEC,NEG为单操作数
SBB为带进位减法
除 DEC不影响 CF标志外,6个状态标志均据结果臵位
NEG求补运算,等价于用 0减去操作数 。
其对标志位的影响,由 0减去该操作数的过程决定 。
例 1 编程完成 2D04H – 3AB0H
执行后,
( AX) =0F254H CF=1,OF=0,SF=1,ZF=0
2D04H 0010 1101 0000 0100
- 3AB0H - 0011 1010 1011 0000
1 1 1111 1 1 111
F254H 1111 0010 0101 0100
MOV AX,2D04H
SUB AX,3AB0H
借位例 2 value 是一个字节变量
OFFSET value = 1000H
( DS) =2000H,( 21000H) =00H
DEC value
执行后,( 21000H) =0FFH
CF=不变,OF=0,ZF=0,SF=1
注意是内存单元内容减 1,而非地址减 1
00 H
- 01 H
11
FFH
例 3 MOV AH,80H
NEG AH
00 H 0000 0000 B
- 80 H - 1000 0000 B
1 1
80H 1000 0000B
执行后:
( AL) =80H CF=1,OF=1,ZF=0,SF=1
例 4 用指令完成两双字相减运算
0546 7A70H
- F001 A543H
MOV AX,7A70H
SUB AX,A543H
MOV BX,0546H
SBB BX,0F001H
CMP oprd1,oprd2 ; (oprd1) - (oprd2)
① 据 ZF判断两数是否相等
CMP A,B
ZF=1 两数相等,A = B;
ZF=0 两数不等,A ≠ B
② 据 ZF和 CF判断两无符号数关系
CF= 1 A低于 B
CF= 0 A高于等于 B
CF=1或 ZF=1 A低于等于 B
CF=0且 ZF=0 A高于 B
利用 CMP执行后的标志值,比较两操作数之间的关系
比较指令 CMP,进行两操作数相减操作,
但只影响标志值,不影响操作数 (减的结果不保存 )
条件转移指令 判断条件低于 JB ne xt CF = 1
低于等于 JB E ne xt CF = 1 或 Z F = 1
高于 JA ne xt CF = 0 且 Z F = 0
高于等于 JA E ne xt CF = 0
CMP AX,BX ;比较
JAE above ;高于等于则跳转
XCHG AX,BX ;低于则交换
above:,、、
例 将 AX和 BX中较大的无符号数,存于 AX中
CMP A,B
③ 用 ZF,SF和 OF判断两带符号数关系
OF=0,不溢出情况,
SF=0,A≥B
SF=1,A< B
OF=0,SF=0 A≥B
OF=0,SF=1 A< B
OF=1,SF=1 A> B
OF=1,SF=0 A< B
0
- 1 正 - 负 = 负,结果 SF = 1,OF=1
1 但,正 > 负,知 A> B
1
- 0 负 - 正 = 正,结果 SF = 0,OF=1
0 但,负 < 正,知 A< B
OF=1,溢出情况,
(由符号位可决定是否溢出 )
结合 ZF,得到结论,
SF
OF
0
0
0
1
1
0
1
1
SF ∨ OF 0 1 1 1
或运算,有 1 则 1,全 0 则 0
逻辑运算:
CM P A,B 两数关系
SF ∨ O F = 0 A ≥ B
SF ∨ O F = 1 A < B
( SF ∨ OF ) ∨ ZF = 0 A > B
( SF ∨ OF ) ∨ Z F = 1 A ≤ B思考:可否只用 ZF 和 SF
判断两符号数关系?
SF
OF
0
0
0
1 0
1
1
SF ∨ OF 0 1 0
异或运算,异则 1,同则 0
条件转移指令 判断条件小于 JL nex t SF ∨ O F = 1
小于等于 J L E nex t ( SF ∨ OF ) ∨ ZF =1
大于 J G next ( SF ∨ OF ) ∨ ZF = 0
大于等于 J G E next SF ∨ O F= 0
例 将 AX和 BX中较大的带符号数,存于 AX中
CMP AX,BX ;比较
JGE great ;大于等于则跳转
XCHG AX,BX ;小于则交换
great:,、、
3,乘法指令指令格式 执行操作
M UL sr c
若 sr c 为字节类型:
( AX ) ← ( AL ) × (sr c )
若 sr c 为字类型:
( DX ),( AX ) ← ( AX ) × (sr c )
将被乘数、乘数看作无符号数,进行乘运算乘的结果也为无带符号数
I M UL sr c
执行的操作与 M U L 相似将被乘数、乘数看作带符号数,进行乘运算乘的结果也为带符号数无符号数乘法带符号数乘法
MUL src
IMUL src
单操作数指令
源操作数 ( 乘数 )类型决定操作类型
目的操作数 (被乘数 ) 隐含 。
字节乘 AL 字乘 AX
字节相乘的结果存放在 AX中字相乘的结果存放在 DX,AX中
MUL 用于无符号数运算
IMUL 用于带符号数运算
影响 CF和 OF,对其他条件码 无定义 ( 不确定 )
指令 MUL
字节相乘,AH=0,CF=OF=0,否则 CF=OF=1
字相乘,DX=0,CF=OF=0,否则 CF=OF=1
对指令 IMUL
字节相乘,AH=0或 AH=FFH,CF=OF=0,否则 CF=OF=1
字相乘,DX=0或 DX=FFFFH,CF=OF=0,否则 CF=OF=1
例 (AL) = 0B4H,(BL) = 11H
指令中源操作数为字节类型,故是字节操作
① MUL BL ② IMUL BL
看作无符号数
(AL) = 180D
(BL) = 17D
180× 17 = 3060D
= 0BF4H
执行 MUL BL后:
(AX) = 0BF4H
看作带符号数
(AL) = -76D
(BL) =17D
(-76)× 17 = -1292D
= 0FAF4H
执行 IMUL BL后:
(AX) = 0FAF4H
例 (AX)=0FFFFH,(BX)=0FFFFH
指令中源操作数为字类型,故是字操作
① MUL BX
执行 MUL BX后:
(DX) = 0FFFEH
(AX) = 0001H
看作无符号数
(AX )= (BX) = 65535
65535× 65535
= 4294836225
= 0FFFE 0001H
② IMUL BX
看作带符号数
(AX)= (BX)=-1
(-1)× (-1)
= 1
= 0000 0001H
执行 IMUL BX后:
(DX) = 0000H
(AX) = 0001H
4,除法指令指令格式 执行操作
D IV sr c
无符号数除法
(sr c) 为字节类型:
( A L) ← ( A X) / (s r c) 的商
( AH ) ← ( A X) / (sr c) 的余数
(sr c) 为字类型:
( AX ) ← D X ),( AX ) / (sr c) 的商
(DX) ← (DX ),( A X) / (sr c ) 的余数将被除数、除数看作无符号数,进行除法运算,
商、余数也为无符号数
ID IV sr c
带符号数除法执行的操作与 D IV 相同,
将被除数、除数看作带符号数,进行除法晕眩商、余数也为带符号数,余数的符号与被除数同
单操作数指令
源操作数 (除数 )类型 决定指令操作类型
目的操作数 (被除数 )隐含字节操作在 AX中;字操作在 DX,AX中
除的结果,字节操作在 AX中;字操作在 DX,AX中
除法指令对所有条件码位均 无定义
下列情况自动转入 0 中断处理:
(1) 除数为 0
(2) 字节操作,商的范围超出字节范围字操作时,商的范围超出字范围除法指令举例例 (AX)=0501H,(BL)=0C6H
(1) DIV BL (2) IDIV BL
看作无符号数 看作带符号数
(AL) = 1281D (AL) = 1281D
(BL) = 198D (BL) = -58D
1281/198商 = 6D 1281/ (-58)商 = -22D=0EAH
余数 =93D=5DH 余数 =5D
执行 DIV BL后,执行 IDIV BL后:
(AX) = 5D06H (AX) = 05EAH
5,符号扩展指令指令格式 执行操作
CBW
将 ( AL ) 的符号扩展到 AH 中
( AL ) 的 D7=0,( AH ) =0 0H
D 7 = 1,( AH ) =FFH
CWD
将 ( AX ) 的符号扩展到 D X 中
(AX ) 的 D15 =0,( DX ) =0 00 0 H
D 1 5 = 1,( DX ) =FFF FH
无操作数格式
操作数隐含字节操作,源在 AL,目的在 AX
字 操 作,源在 AX,目的在 DX,AX
对条件码无影响
符号扩展指令应对带符号数操作
扩展后,表示的数值大小不变,只是位数发生变化
8位 16位 16位 32位
应用场合:
除法指令中,使被除数满足要求 。
字节操作,被除数为 16位字操作,被除数为 32位加减运算中,使两操作数类型一致如:字与字节相加,减时如:双字与字之间的相加,减时符号扩展指令举例例 CBW
执行前 (AL)=01H,(AH)=0FFH
执行后 (AL)=01H,(AH)=00H
例 CWD
执行前 (AX)=0FF00H,(DX)=0011H
执行后 (AX)=0FF00H,(DX)=0FFFFH
例 ( AL) =0FFH,将其内容扩展至 (AX)中看作无符号数为 255,
若用 MOV AH,0H
(AX)=00FFH=255D
若用 CBW
(AX)=0FFFFH=65535≠原数故,对无符号数的扩展不能用符号扩展指令对无符号数的扩展,直接给高位赋 0。