295
第3第 8086 第第第第第第第第 3.1 8086 第第第第3.2 第第第第第第第第第 3.3 第第第第第第第第第第

第 3 章 8086 汇编语言程序设计

  • Upload
    soyala

  • View
    165

  • Download
    0

Embed Size (px)

DESCRIPTION

第 3 章 8086 汇编语言程序设计. 3.1 8086 的指令系统 3.2 汇编语言的基本语法 3.3 汇编语言程序设计基础. 3.1 8086 的指令系统. 3.1.1 8086 的寻址方式. 与数据有关的寻址方式 : 以 MOV 指令为例 立即寻址 MOV AX , 3069H 寄存器寻址 MOV AL , BH 直接寻址 MOV AX , [ 2000H ] 寄存器间接寻址 MOV AX , [ BX ] - PowerPoint PPT Presentation

Citation preview

Page 1: 第 3 章   8086 汇编语言程序设计

第 3 章 8086 汇编语言程序设计

3.1 8086 的指令系统3.2 汇编语言的基本语法3.3 汇编语言程序设计基础

Page 2: 第 3 章   8086 汇编语言程序设计

3.1.1 8086 的寻址方式 与数据有关的寻址方式:以 MOV 指令为例

• 立即寻址 MOV AX , 30

69H

• 寄存器寻址 MOV AL , BH

• 直接寻址 MOV AX , [ 2

000H ]

• 寄存器间接寻址 MOV AX , [ BX ]

• 寄存器相对寻址 MOV AX , COUNT [ S

I ]

• 基址变址寻址 MOV AX , [ BP ] [

DI ]

• 相对基址变址寻址 MOV AX , MASK [ BX ] [

SI ]

存储器寻址

3.1 8086 的指令系统

Page 3: 第 3 章   8086 汇编语言程序设计

(1) 立即寻址方式 * —— 操作数在指令中给出

MOV AL, 5

MOV AX, 3064H

MOV AL, ‘A’

* 只能用于 SRC 字段

* SRC 和 DST 的字长一致 MOV AH, 306

4H

Page 4: 第 3 章   8086 汇编语言程序设计

(2) 寄存器寻址方式 * —— 操作数在指定的寄存器中

MOV AX, BX

MOV AL, BH

MOV AX, 3064H

* 字节寄存器只有 AH AL BH BL CH CL DH DL

* SRC 和 DST 的字长一致 MOV AH,

BX

* CS 不能用 MOV 指令改变 MOV CS, A

X

Page 5: 第 3 章   8086 汇编语言程序设计

(3) 直接寻址方式 * —— 有效地址 EA 由指令直接给出 例: MOV AX, [ 2000H ]

EA=2000H, 假设 (DS)=3000H, 那么 PA=32000H

* 隐含的段为数据段 DS* 可使用段跨越前缀 MOV AX, ES: [2000H]* 操作数地址可由变量(符号地址)表示

VALUE DB 10

MOV AH, VALUE

MOV AX, VALUE MOV AX, WORD PTR VALUE

5030

32000

AH AL

30 50

(AX) = 3050H

Page 6: 第 3 章   8086 汇编语言程序设计

例 将地址为 2000H 和 2001H 的两内存单元内容相加, 结果存在地址 2002H 单元中,程序如下: A0 00 20

02 06 01 20A2 02 20

数据暂存器

PSW 标志寄存器 控制电路

指令译码器

AXBXCXDXSIDIBPSP

寄存器组

指令队列

总线接口控制电路

运算器

地址总线 AB

数据总线 DB

控制总线 CB

IP

地址加法器

DSES

SSCS

1010 00000000 00000010 00000000 00100000 01100000 00010010 00001010 00100000 00100010 0000

A0002002060120A20220

MOV AL , [2000H]

ADD AL , [2001H]

MOV [2002H], AL

Page 7: 第 3 章   8086 汇编语言程序设计

(4) 寄存器间接寻址 * —— EA 在基址寄存器 (BX/BP)

变址寄存器 (SI/DI) 中 MOV AX, [BX] PA = 16d (DS) + (BX)

MOV AX, ES:[BX] PA = 16d (ES) + (BX)

MOV AX, [BP] PA = 16d (SS) + (BP)

* 不允许使用 AX 、 CX 、 DX 存放 EA

MOV AX, [CX]

* SRC 和 DST 的字长一致 MOV DL, [ BX ] ; [BX] 指示一个字节单元 MOV DX, [ BX ] ; [BX] 指示一个字单元

* 适于数组、字符串、表格的处理

Page 8: 第 3 章   8086 汇编语言程序设计

有效地址 =

(BX)

(BP) 8 位

(SI) 16 位

(DI)

+ 位移量

(5) 寄存器相对寻址方式 *

例: MOV AX, COUNT[SI] 或

MOV AX, [COUNT+SI]

假设 (DS)=3000H, (SI)=2000H, COUNT=3000H,

那么 PA = 35000H

假设 (35000H)=1234H, 那么 (AX)=1234H

Page 9: 第 3 章   8086 汇编语言程序设计

(6) 基址变址寻址方式 *

MOV AX, [BX][DI]

或 MOV AX, [BX+DI]

MOV AX, ES:[BX][SI]

有效地址 =(BX) (SI)

(BP) (DI)+

Page 10: 第 3 章   8086 汇编语言程序设计

(7) 相对基址变址寻址方式

MOV AX, MASK[BX][SI]

或 MOV AX, MASK[BX+SI]

或 MOV AX, [MASK+BX+SI]

有效地址 =(BX) (SI) 8 位

(BP) (DI) 16 位+ + 位移量

Page 11: 第 3 章   8086 汇编语言程序设计

80x86 新增的寻址方式 EA = ( 基址寄存器 ) + ( 变址寄存器 ) 比例因子 + 位移量

(1) 比例变址寻址方式 例: MOV EAX, COUNT [ ESI 4 ]

Page 12: 第 3 章   8086 汇编语言程序设计

(2) 基址比例变址寻址方式 例: MOV ECX, [ EAX ][ EDI 4 ]

(3) 相对基址比例变址寻址方式 例: MOV EAX, TABLE [ EBP ][ EDI 4 ]

Page 13: 第 3 章   8086 汇编语言程序设计

▲ 立即数寻址、寄存器寻址的操作数, 不用在取完指令后再到内存中取数。

CPU 总线 内存

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB

Page 14: 第 3 章   8086 汇编语言程序设计

▲以下的 5 中寻址方式, 操作数存放在内存中,取完指令后,还需到内存取数。 指令中给出的是该操作数的地址,包括段地址和偏移地址。

CPU 总线 内存

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB

Page 15: 第 3 章   8086 汇编语言程序设计

例 编程将 CL 寄存器的内容传送到 21000H 单元中。

MOV AX, 2000H

MOV DS, AX ; (DS) = 2000H

MOV DI, 1000H ; (DI) = 1000H

MOV DS: [ DI ], CL ;(21000H) = (CL)

地址 21000H = 2000 : 1000H

编程时, DS 存放段地址 2000H

DI 存放偏移地址 1000H

如指令 MOV DS: [ DI ] , CL

功能:将 CL 寄存器中的内容传送到以 DS 为段值, DI 为偏移值的内存单元中

Page 16: 第 3 章   8086 汇编语言程序设计

通过例子看到:在相应的寄存器中设定段值和偏移值,由地址加法器送出 20 位的地址信号,对选中的内存单元进行操作。

数据暂存器

PSW 标志寄存器 执行部件

控制电路

指令译码器

AXBXCXDXSIDIBPSP

寄存器组

指令队列

总线接口控制电路

运算器

地址总线 AB

数据总线 DB

控制总线 CB

器21000H21001H21002H

IP

地址加法器

DSES

SSCSA0

1000

21000MOV AX, 2000H

MOV DS, AX

MOV DI, 1000H

MOV DS: [ DI ], CL

20002000

A0

Page 17: 第 3 章   8086 汇编语言程序设计

内存单元的地址由段地址和偏移地址构成

▲ 为减短指令长度指令中 :

只给出偏移地址的来源,段地址由默认关系给出。 MOV AL , [ 2000H ]

▲ CPU 根据偏移地址给出的方式, 按默认关系自动选择段寄存器,获取段值, 由段值、偏移值构成操作数所在内存单元的物理地址。

上例 PA= ( DS ) ×10H + 2000H

即选择 DS 寄存器的内容为段地址。

Page 18: 第 3 章   8086 汇编语言程序设计

指令中用 [ ] 给出偏移地址。 操作数的偏移地址又称有效地址 EA ( Efficient Address)

▲按给出偏移地址方式的不同,分为以下 5 种:

直接寻址 MOV AL, [ 1000H ]

寄存器间接寻址 MOV AL, [ BX ]

寄存器相对寻址 MOV AL, [ BX + 10H ]

基址加变址寄存器 MOV AL, [ BX + SI ]

相对基址加变址寄存器 MOV AL, [ BX + SI + 10H ]

Page 19: 第 3 章   8086 汇编语言程序设计

寄存器间接寻址( Register indirect addressing )

操作数放在存储器里,操作数的有效地址 EA 由寄存器给出 ,

寄存器的内容为操作数的有效地址。

可用的寄存器有 BX 、 SI 、 DI  、 BP

如 : MOV AL, [ BX ]

MOV AH, [ SI ]

MOV DL, [ DI ]

MOV DH, [ BP ]

Page 20: 第 3 章   8086 汇编语言程序设计

默认段寄存器的关系:

① 使用 BX 、 SI 、 DI ,默认段寄存器为DS

(BX)

PA = ( DS )×10H + (SI)

(DI)

② 使用 BP ,默认段寄存器为 SS

PA = ( SS )×10H + ( BP )

Page 21: 第 3 章   8086 汇编语言程序设计

使用 BX 、 SI 、 DI 的寄存器寻址,默认段寄存器为 DS

CPU 总线 内存

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB

Page 22: 第 3 章   8086 汇编语言程序设计

使用 BP 的寄存器寻址,默认段寄存器为 SS

CPU 总线 内存

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB

Page 23: 第 3 章   8086 汇编语言程序设计

例: MOV AX , [ DI ]

若 ( DS ) = 3000H

( DI ) = 2000H

则内存操作数的物理地址为:

PA = ( DS )×10H + ( DI )

= 32000H

执行后 (AX) = (32000H) = 400BH

32000 0B

05

8B指 令

40

思考: 指令 MOV AX,[ DI ] 与指令 MOV AX, DI 有什么不同?

Page 24: 第 3 章   8086 汇编语言程序设计

▲内存操作数按给出偏移地址方式的不同,有以下 5 种寻址方式:

直接寻址 MOV AL, [ 1000H ]

寄存器间接寻址 MOV AL, [ BX ]

寄存器相对寻址 MOV AL, [ BX + 10H ]

基址加变址寄存器 MOV AL, [ BX + SI ]

相对基址加变址寄存器 MOV AL, [ BX + SI + 10H ]

存储器操作数的段地址按默认关系得到。特点:有 BP 默认 SS

无 BP 默认 DS

寻址方式的几点说明:

Page 25: 第 3 章   8086 汇编语言程序设计

1 .不自创寻址方式 内存操作数地址只能由 BX 、 BP 、 SI 、 DI 给出 ,

它们的组合也不是任意的。

基址加变址

[ BX+SI ][ BX+DI][ BP+SI ][ BP+DI]

寄存器相对

[SI + X ][DI + X ][BX + X ][BP + X ]

寄存器间接

[SI ][DI ][BX ][BP ]

相对基址加变址

[ BX+SI+X ][ BX+DI+X][ BP+SI+X ][ BP+DI+X]

X为 8位或16位偏移量

Page 26: 第 3 章   8086 汇编语言程序设计

只有存储器操作数需用段跨越的前缀

ES : MOV [SI] , CX

DS : MOV AL , [BP]

MOV ES : AX , 0

CS: MOV CX, 22H

Page 27: 第 3 章   8086 汇编语言程序设计

除此之外,其他方式均错误。

如 MOV CL, [AX]

MOV AX, [DX]

MOV AL, [CX]

MOV CX, [BP+BX]

MOV AH, [SI+DI]

MOV BL, [AX+CX]

Page 28: 第 3 章   8086 汇编语言程序设计

D:\>DEBUG -A 0AFA:0100 MOV CL, [AX] ^ Error0AFA:0100 MOV AX, [DX] ^ Error0AFA:0100 MOV AL, [CX] ^ Error0AFA:0100 MOV CX, [BP+BX] ^ Error0AFA:0100 MOV AH, [SI+DI] ^ Error0AFA:0100 MOV BL, [AX+CX] ^ Error0AFA:0100 -

利用 DEBUG 可判断下列寻址方式错:

Page 29: 第 3 章   8086 汇编语言程序设计

3.1.2 8086/8088 的指令系统

一 . 概述

二 . 数据传送指令

三 . 算术运算指令

四 . 逻辑运算指令

五 . 控制转移指令

六 . 处理机控制指令

七 . 串操作指令

Page 30: 第 3 章   8086 汇编语言程序设计

一.概述

8086/8088 的指令系统中共有 92 种基本指令。

可以分成 6 个功能组:

数据传送 (Data transfer)

算术运算( Arithmetic )

逻辑运算和移位指令 (Logic& Shift)

串操作 (String manipulation)

控制转移( Control Transfer )

处理器控制( Processor Control )

Page 31: 第 3 章   8086 汇编语言程序设计

先介绍以下内容:1. 指令助记符表

2. 学习指令的要点

3. 利用 DEBUG 程序,学习指令系统

4. 指令中操作数的表示

5. 书写指令注意事项

Page 32: 第 3 章   8086 汇编语言程序设计

指令类型 助记符通用传送 MOV, PUSH, POP, XCHG, XLAT

地址传送 LEA, LDS, LES

标志传送 PUSHF, POPF, LAHF, SAHF

数据传送 输入输出 IN, OUT

加法 ADD, ADC, INC, AAA, DAA

减法 SUB, SBB, DEC, NEG, CMP, AAS, DAS

乘法 MUL, IMUL, AAM

除法 DIV, IDIV, AAD

算术运算

符号扩展 CBW, CWD

逻辑运算 AND, TEST, OR, XOR, NOT

移位 SHL, SAL, SHR, SAR逻辑操作 循环移位 ROL, ROR, RCL, RCR

1. 指令助记符表

Page 33: 第 3 章   8086 汇编语言程序设计

指令类型 助记符串操作 MOVS,CMPS,SCAS,LODS,STOS串

处理 重复控制 REP,REPE/REPZ,REPNE/REPNZ

无条件转移 JMP

条件转移

JE/JZ, JNE/JNZ, JS, JNS, JO, JNO

JP, JNP, JC, JNC, JCXZ

JA/JNBE, JAE/JNB, JB/JNAE, JBE/JNA

JG/JNLE, JGE/JNL, JL/JNGE, JLE/JNG

循环控制 LOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ

过程调用 CALL, RET

控制转移

中断指令 INT, INTO, IRET

处理机控制CLC, STC, CMC,CLD, STD, CLI, STI

NOP, HLT, WAIT, ESC, LOCK

Page 34: 第 3 章   8086 汇编语言程序设计

2. 学习指令的要点

从以下几个方面来掌握一条指令 :

指令的助记符 指令的格式:操作数的个数、类型( B , W , DW ) 执行的操作:指令执行后的结果

包括 : 哪些寄存器、内存单元的值发生了变化 对标志位有无影响,哪些受影响

特点及注意事项

只介绍常用的指令,其他需要时可自学。

Page 35: 第 3 章   8086 汇编语言程序设计

D:\>DEBUG - A ; 汇编指令0AF8:0100 MOV AL,B5 0AF8:0102 ADD AL, 8F 0AF8:0104 - R ; 显示指令执行前各寄存器的值 AX=0000 BX=0000 CX=0000 DX=0000 、、、、、、CS=0AF8 IP=0100 NV UP EI PL NZ NA PO NC- T=100 2 ; 执行指令,查看结果AX=0044 BX=0000 CX=0000 DX=0000 、、、、、、CS=0AF8 IP=0104 OV UP EI PL NZ AC PE CY0AF8:0104 2080FC01 AND [BX+SI+01FC], AL-

1 0 1 1 0 1 0 1 + 1 0 0 0 1 1 1 1

进位 1 1 1 1 1 1 1 0 1 0 0 0 1 0 0

编程完成 B5h + 8Fh = ? 学习加法 ADD 指令及其对状态标志位的影响。

3. 利用 DEBUG 学习指令系统(示例)

Page 36: 第 3 章   8086 汇编语言程序设计

4. 指令中操作数的表示

符号 表示内容data 立即数操作数

reg通用寄存器操作数 8 位:AH、AL、BH、BL、CH、CL、DH、DL

16 位:AX、BX、CX、DX、BP、SP、SI、DIsegreg 段寄存器 CS 、DS、SS、ESmem

或 [ ] 存储器操作数(5种寻址方式)

src 源操作数dst 目的操作数

( ) 注释时表示寄存器、存储器、端口的内容oprd1oprd2

两操作数

Page 37: 第 3 章   8086 汇编语言程序设计

5. 书写指令注意事项:

不区分字母的大小写。

下列写法表示同一条指令:

MOV AX , 1ABDH

mov ax, 1abdh

不添加指令系统没有的指令,即不自创助记符。

将 MOV AL , 0 写成 MOVE AL ,0

JMP lable 写成 JUMP lable

Page 38: 第 3 章   8086 汇编语言程序设计

注意操作数的范围

对字节操作指令 0 ~ FFH 0 ~ 255

对字操作指令 0 ~ FFFFH 0 ~ 65535

MOV AL , 260

MOV AX , 70000

MOV AL, 1FFH

MOV AL, 2ABCDH

Page 39: 第 3 章   8086 汇编语言程序设计

对无操作数指令,不添加操作数。

STC AL

对单操作数指令,操作数不能是立即数。

IMUL 6

Page 40: 第 3 章   8086 汇编语言程序设计

对双操作数指令

① 不能两个同为存储器操作数 MOV [ DI ] , [ SI ]

② 目的操作数不能是立即数 ADD 3 , AL ③ 两个操作数的类型应相同 SUB AX , BL

若 value 定义为字类型存储器变量:

MOV CL, value [ BX ]

Page 41: 第 3 章   8086 汇编语言程序设计

内存操作数的属性应明确。

MOV [ BX ] , 0

MOV byte ptr [ BX ] , 0

MOV word ptr [ BX ] , 0

MOV [ BX ] , AL

MOV [ BX ] , AX

Page 42: 第 3 章   8086 汇编语言程序设计

A 、 B 、 C 、 D 、 E 、 F开头的十六进制数前面加 0 ,

与 H 结尾的标识符区别。

如 寄存器名: AH 、 BH 、 CH 、 DH

变量名 : abcdH 等

例 mov AL, 0AH

mov AL, AH

mov BX, 0abcdH

Page 43: 第 3 章   8086 汇编语言程序设计

CS 和 IP 的值只在控制转移指令中修改。

对非控制转移指令,取完指令后 IP 值自动 指向下条指令。

段寄存器 CS 的值,只在 MOV 、 PUSH 中可作操作数, 且这两条指令执行结果不改变 CS 值。

MOV AX, CS

PUSH CS

IP 、 PSW 两个寄存器不作为操作数在指令中出现。mov IP , 1234H

mov PSW , 0F0FH

PSW 状态寄存器的值由指令执行后确定, 不同的指令对各标志的影响不同。

Page 44: 第 3 章   8086 汇编语言程序设计

二 .数据传送指令

地址总线 AB

存储器

I/O接口

输入设备

I/O接口

数据总线 DB

控制总线 CB

输出设备

CPU

寄存器,存储器, I/O 端口

Page 45: 第 3 章   8086 汇编语言程序设计

▲ 数据传送是最基本、最重要的一种操作

实际程序中,使用的比例最高

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 端口

设置寄存器、内存单元的初始值

Page 46: 第 3 章   8086 汇编语言程序设计

▲ 按传送内容,可分为四类:

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这三条允许

Page 47: 第 3 章   8086 汇编语言程序设计

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 )

Page 48: 第 3 章   8086 汇编语言程序设计

例 : ①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 BYTE PTR [ value ] , 0 MOV WORD PTR [ BX ] , 1

Page 49: 第 3 章   8086 汇编语言程序设计

MOV 指令特点及注意事项 :

双操作数指令 ( 注意双操作指令的特点)

可进行字节或字传送 不允许存储器传送到存储器

MOV [ BX ] , value

MOV [DI] , [SI]

MOV AX , value

MOV [ BX ] , AX

MOV AL , [SI]

MOV [ DI ] , AL

Page 50: 第 3 章   8086 汇编语言程序设计

可对 DS 、 ES 、 SS 赋值 但不允许立即数直接传送给段寄存器

MOV DS , AX

MOV ES , [BX]

MOV DS , 1000H

MOV AX , 1000H

MOV DS , AX

CS 不能做目的操作数 , 不能通过传送指令改变 CS 的值

MOV CS , AX

Page 51: 第 3 章   8086 汇编语言程序设计

不允许段寄存器传送到段寄存器

MOV ES , DS

MOV AX , DS MOV ES , AX

D:\MASM>DEBUG-A1693:0100 MOV ES, DS ^ Error1693:0100 MOV AX, DS1693:0102 MOV ES, AX1693:0104-

Page 52: 第 3 章   8086 汇编语言程序设计

例 编程将 CL 寄存器的内容传送到 200:100H 单元中。

MOV AX, 200H

MOV DS , AX ; (DS) = 200H

MOV [100H ], CL ;(02100H) = (CL)

编程 1 :

MOV AX, 200H

MOV DS , AX ; (DS) = 200H

MOV DI , 100H ; (DI) = 100H

MOV [ DI ], CL ;(02100H) = (CL)

编程 2 :

MOV [200:100H ], CL

Page 53: 第 3 章   8086 汇编语言程序设计

MOVMOV 指令应用(自学)指令应用(自学)

例:

实现将 AREA1开始的 100 个数据传送到 AREA2开始的单元。

… …

AREA1: AREA2:

100 个数据

Page 54: 第 3 章   8086 汇编语言程序设计

分析题意:

①可以用 200 条 MOV 指令来完成 100 个数据传送,

指令操作重复,每个数据传送后的地址是变化的。

② 可以利用循环,

但每循环一次要修改地址(源地址和目的地址),

必须把地址放在寄存器当中,用寄存器间接寻址来寻找操作数 .

Page 55: 第 3 章   8086 汇编语言程序设计

得到如下程序:

…MOV SI , OFFSETOFFSET AREA1

MOV DI , OFFSETOFFSET AREA2

MOV CX , 100

AGAIN : MOV AL , [SI]

MOV [DI] , AL

INC SI INC SI ;修改地址指针;修改地址指针

INC DI INC DI ;修改地址指针;修改地址指针

DEC CXDEC CX ;修改个数;修改个数

JNZ AGAIN

Page 56: 第 3 章   8086 汇编语言程序设计

MOV 指令的字节数、时钟周期数、 CPU 与内存间传送次数(自学 P31~34 )

字节 例时钟数 M传送到 CPU 次数MOV 指令操作数

AX M M AX

10(14) 1 3 MOV COUNT[DI], AX

R R

10(14) 1 3 MOV AX,TEMP

2 2 MOV DS,BX

M R

R M

8(12)+ EA 1 2~4 MOV BP,STAK_TOP

9(13)+ EA 1 2~4 MOV COUNT[BX][SI],CX

R(段寄存器除外) 4 2~3 MOV CL,2

M 10(14)+ EA 1 3~6 MOV word ptr [BP],5H

R段 R 16

(CS 、 IP 除外)2 2

MOV ES,CXMOV BP,SS

M R 段R段 M

8(12)+ EA 1 2~4 MOV DS,SEG_BASE

9(13)+ EA 1 2~4MOV[BX]SEG_SAN,CS

data

data

Page 57: 第 3 章   8086 汇编语言程序设计

计算计算 EA EA 需要的 时钟数:需要的 时钟数:如下表所示 : ( 若段超越,再加两个时钟 T周期 )

寄存器间接寻址

寻址方式 计算 EA 所需时间

直接寻址

寄存器相对寻址

基址加变址寻址[BP+DI], [BX+SI]

[BP+SI], [BX+DI]

相对基址加变址寻址[BP+DI+ 位移量】 , [BX+SI+ 位移量 ]

[BP+SI+ 位移量】 , [BX+DI+ 位移量 ]

6T

5T

9T

7T

8T

11T

12T

Page 58: 第 3 章   8086 汇编语言程序设计

(( 22 )指令字节数)指令字节数:

指令字节数与寻址方式有关。

• 通常操作码占二个字节; • 立即寻址 : 立即数增加 1-2 个字节数;• 操作数在内存中 :

直接寻址 : 直接地址为 1-2 个字节,总的指令长 3-4个字节;

寄存器间接寻址(没有位移量) : 2 个字节;

变址寻址或者相对基址加变址 : 都有 1-2 字节的位移量,

指令字节数为 2-4 个 字节。

Page 59: 第 3 章   8086 汇编语言程序设计

(( 33 )传送次数:)传送次数:

指执行指令时,内存与 CPU 之间数据传送的次数。

凡是立即数→寄存器或寄存器之间的传送无此传送数。

凡是寄存器与存储器之间传送次数为 1 。

Page 60: 第 3 章   8086 汇编语言程序设计

2. 2. 输入输出指令输入输出指令( Input and Output)

输入输出指令共两条:

( 1 )1 ) 、、 ININ (Input byte or word)

( 2 )2 ) 、、 OUTOUT (Output byte or word)

输入指令用于 CPU 从外设端口接受数据,

输出指令用于 CPU向外设端口发送数据。

无论接受还是发送数据,必须通过累加器 AX( 字)或 AL( 字节),

又称累加器专用传送指令 。

输入、输出指令不影响标志位。输入、输出指令不影响标志位。

Page 61: 第 3 章   8086 汇编语言程序设计

每个外设要占几个端口:数据口,状态口和控制口。

CPUI/O设备

译码

数据端口DB

AB

CB

I/O接口

状态端口

控制端口

Page 62: 第 3 章   8086 汇编语言程序设计

由图可见:信息交换要通过端口:由图可见:信息交换要通过端口:在 IBMPC 机里,可以配接许多外部设备,

每个外设与 CPU 之间交换数据,状态信息和控制命令,

每一种信息交换都要通过一个端口来进行。

端口数:外部设备最多有 65536 个 I/O 端口。

A0~A15译码形成。

端口号:端口号(即外设端口地址)为 0000H~FFFFH 。

PC 机仅使用 A0~A9译码形成 I/O 口地址,即 1024H 个口地址

端口号: 0000H~03FFH

其中: A9=1 ,表示扩充槽上的口地址。

Page 63: 第 3 章   8086 汇编语言程序设计

长格式:长格式:

端口号中前端口号中前 256256 个端口(个端口( 0~FFH0~FFH )),可以直接写在指令中,

端口号代替指令中的 PORT ,

机器指令用二字节表示,第二字节就是端口号。

短格式:短格式:

当端口号≥当端口号≥ 256256 时,只能使用短格式时,只能使用短格式,

必须先把端口号放到 DX 寄存器中。

不需要用任何段寄存器来修改它的值。

Page 64: 第 3 章   8086 汇编语言程序设计

(1)(1) 、、 IN (Input byte or word) IN (Input byte or word) 输入指令输入指令

格式: IN acc, port ;(acc) (port)

具体形式有四种:

长格式长格式 : : IN AL, data8 ; 端口地址 8 位,输入一个字节

IN AX, data8 ;端口地址 8 位,输入一个字

短格式短格式 : : IN AL, DX ;端口地址 16 位,输入一个字节

IN AX, DX ;端口地址 16 位,输入一个字

必须通过累加器 AX( 字)或 AL( 节)输入数据。

Page 65: 第 3 章   8086 汇编语言程序设计

(2 )(2 ) 、、 OUTOUT(Output byte or word) 输出指令输出指令格式: OUT port, acc ;(port) (acc)

具体形式有四种:

长格式长格式 :: OUT data8 , AL ; 端口地址 8 位,输出一个字节

OUT data8, AX ;端口地址 8 位,输出一个字

短格式短格式 :: OUT DX , AL ;端口地址 16 位,输出一个字节

OUT DX , AX ;端口地址 16 位,输出一个字

必须通过累加器 AX( 字)或 AL( 节)输出数据。

Page 66: 第 3 章   8086 汇编语言程序设计

例 1 :实现 (29H) ( 28H )→( DATA_WORD )

长格式长格式 :: IN AX , 28H

MOV DATA_WORD , AX

例 2 :从端口 3FCH 送一个字到 AX 寄存器

短格式短格式 :: MOV DX , 3FCH

IN AX , DX ; ( AL )←( 3FCH ),

( AH )←( 3FDH )

例 3 :实现将( AL) →(05H)

长格式长格式 :: OUT 5 , AL;( 05H )←( AL )

Page 67: 第 3 章   8086 汇编语言程序设计

3 . PUSH (Push word onto stack)

POP (Pop word off stack)

这是两条堆栈操作指令。

(1)(1)先介绍一下什么是堆栈,为什么需要堆栈先介绍一下什么是堆栈,为什么需要堆栈

堆栈是按照先进后出原则组织的一段内存区域。 通常用于存放一些重要数据 ,

如:程序的地址、或是需要恢复的数据。

为方便数据的存放和恢复, 设置专门的指针,指向堆栈中要操作的单元。 段值由 SS 给出,偏移地址由 SP 给出

SS → 堆栈段寄存器 (stack segment)

SP → 堆栈指针寄存器 (stack point)

SS:SP

Page 68: 第 3 章   8086 汇编语言程序设计

特点:特点:• 下推式的(规定堆栈设置在堆栈段内)改变 SP 的内容,

随着推入堆栈内容增加, SP 的值减少。• 先进后出工作原则( Last In First Out 简称 LIFO)

• 堆栈在内存中的情况:

Page 69: 第 3 章   8086 汇编语言程序设计

• 堆栈在内存中的情况:堆栈在内存中的情况: 可以用一条立即数传送指令给 SP赋值,确定 SP 在 SS 段中的初始位置。

例:设: (SS)=9000H , 堆栈段为 64KB

MOV SP,0E200H ;(SP)=0E200H

则: 整个堆栈段的物理地址范围为:

90000H~9FFFFH90000H~9FFFFH

栈顶的物理地址为:栈顶的物理地址为: 9E200H9E200H

堆栈在内存中的情况如右图所示:

. . .

. . .

偏移地址 物理地址00000H(低地址)

90000H

9E200H

9FFFFHFFFFH

(SP)=E200H

0000H

堆栈段

堆栈在内存中的情况

Page 70: 第 3 章   8086 汇编语言程序设计

(2) (2) 堆栈操作指令堆栈操作指令 (堆栈操作指令有两条 ) :

入栈指令入栈指令格式: PUSH src ; (SP) (SP)-2

((SP)+1,(SP)) (src)

把一个字从源操作数把一个字从源操作数 (src)(src) 由由 SPSP 指向堆栈顶部。指向堆栈顶部。

出栈指令出栈指令格式: POP dest ;(dest) ((SP)+1,(SP))

(SP) (SP)+2

把现行把现行 SPSP 所指向堆栈顶部的一个字 所指向堆栈顶部的一个字 指定的目的操作数 指定的目的操作数 ((destdest)) ,,

同时进行修改堆栈指针的操作。同时进行修改堆栈指针的操作。

SS:SP

SS:SP (src)

SS:SP

SS:SP (dst)

Page 71: 第 3 章   8086 汇编语言程序设计

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)

Page 72: 第 3 章   8086 汇编语言程序设计

例: PUSH AX

若执行前: ( SS ) = 2000H

( SP ) = 1002H

( SS : SP ) = 2010H

( AX ) = 1234H

3B2A

10

高20

地址

SS:SP2000:1002

指令执行前(AX)=1234h

则执行后: ( SS ) = 2000H

( SP ) = 1000H

( SS : SP ) = 1234H

( AX ) = 1234H

1234

10

高20

地址SS:SP

2000:1000

指令执行后(AX)=1234h

不变 减 2 变不变

Page 73: 第 3 章   8086 汇编语言程序设计

D:\MASM>DEBUG-A ;汇编两条指令1693:0100 MOV AX, 12341693:0103 PUSH AX1693: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 NC1693: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 NC1693: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 FF FF FF FF .........…-

例 利用 DEBUG 学习 PUSH 指令

注意相关寄存器和内存单元内容的变化

Page 74: 第 3 章   8086 汇编语言程序设计

特点 :

单操作数指令操作数为 16 位,可以是 reg/segreg/mem, 不可以是 data

reg : AX, BX, CX, DX, SI, DI, BP, BX

segreg : DS, ES, SS, 不允许是 CS

mem : 字类型

POP 出栈操作

SS:SP

SS:SP (dst)

格式 POP dst

执行 ( dst ) ← ( SS : SP )

( SP ) ←( SP ) + 2

Page 75: 第 3 章   8086 汇编语言程序设计

若执行前: ( SS ) = 2000H

( SP ) = 1000H

( SS : SP ) = 1234H

( BX ) = 5678H

1234

10

高20

SS:SP2000:1000

指令执行前

地址

(BX)=5678h

例: POP BX

1234

10

高20

SS:SP2000:1002

指令执行后

地址

(BX)=1234h

则执行后: ( SS ) = 2000H

( SP ) = 1002H

( SS : SP ) = 2010H

( BX ) = 1234H

不变 加 2

变 变

Page 76: 第 3 章   8086 汇编语言程序设计

-A 1693:0100 MOV BP, SP ; 取当前栈顶地址 1693:0102 MOV WORD PTR [BP], 1234 ; 用 MOV 指令使栈顶内容为 1234H1693:0107 POP BX ; 出栈指令1693:0108-R ; 查看指令执行前状态AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=1693 ES=1693 SS=1693 CS=1693 IP=0100 NV UP EI PL NZ NA PO NC1693: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=0000DS=1693 ES=1693 SS=1693 CS=1693 IP=0102 NV UP EI PL NZ NA PO NC1693: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=0000DS=1693 ES=1693 SS=1693 CS=1693 IP=0107 NV UP EI PL NZ NA PO NC1693:0107 5B POP BX-T ; 执行 pop 指令,注意 BX, SP 的变化AX=0000 BX=1234 CX=0000 DX=0000 SP=FFF0 BP=FFEE SI=0000 DI=0000DS=1693 ES=1693 SS=1693 CS=1693 IP=0108 NV UP EI PL NZ NA PO NC1693:0108 F5 CMC-

例 在 DEBUG 下学习 POP 指令

Page 77: 第 3 章   8086 汇编语言程序设计

例:执行下列程序段 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

3412

执行①后 3000:200C

SS:S

P 0B0A

3000:200A

SS:S

P 执行②后 0D

0C0B0A

3000:200CSS:SP 执行⑤后 : (BX)=0C0D

0D0C0B0A

执行 ③④后 (AX)=0066 (BX)=0099执行 ③④后 (AX)=0066 (BX)=0099

3000:200A

SS:S

P 执行②后 0D

0C0B0A 执行⑥后 : (AX)=0A0B

3000:200ESS:SP

(BX)=0C0D

执行 ③④后 (AX)=0066 (BX)=0099

0D0C0B0A

Page 78: 第 3 章   8086 汇编语言程序设计

用 PUSH往 SS 段传送一批数据后,再用 POP 取出时,取出单元的顺序与存放时的顺序正好相反,“后进先出”

⑥ POP AX (AX)=0A0B①PUSH AX

3000:200E

SS:S

P 执行前

3000:200CSS:SP

3000:200ASS:SP ②PUSH BX

3000:200ESS:SP

3000:200CSS:SP

0D0C0B0A3412

⑤ POP BX (BX)=0C0D

(AX)=0A0B (BX)=0C0D

④MOV AX,0066 ; (BX)=0099

③MOV AX,0066 ; (AX)=0066

Page 79: 第 3 章   8086 汇编语言程序设计

堆栈使用的场合

用堆栈保存恢复信息

子程序的调用、返回以及中断调用、返回

用堆栈传送数据 (程序设计中介绍)

Page 80: 第 3 章   8086 汇编语言程序设计

主程序 子程序 :

子程序:在一个实际程序中,有些操作要执行多次,

把要重 复执行( subroutine )操作编为子程序。

也常把一些常用的操作标准化、通用化的子程序。

主程序( Main program )——往往要调用子程序

或处理中断 ,

暂停主程序,执行子程序或中断服务程序。

Page 81: 第 3 章   8086 汇编语言程序设计

调用子程序时需调用子程序时需保留内容保留内容 : :

① 调用子程序:将调用子程序:将 CALLCALL 下条指令地址即下条指令地址即 IPIP 值保留下来值保留下来

( 8088 中码段寄存器 CS 和指令指针 IP ),

才能保证子程序执行完后准确返回主程序继续执行。保证子程序执行完后准确返回主程序继续执行。

② 执行子程序时执行子程序时,

通常用到内部寄存器,执行结果会影响标志位,

必须在调用子程序之前将现状保护起来现状保护起来。

③ 子程序嵌套或子程序递归(自调自)

保留许多信息,而且保证正确返回(且后进先出)。

后保留先取出原则(即 LIFO-LAST In First out )。

Page 82: 第 3 章   8086 汇编语言程序设计

注意: SP——堆栈指针 ,始终指向栈顶。

SP初值用 MOV SP, data 来设定。

下边详细说明一下堆栈用途:下边详细说明一下堆栈用途:

Page 83: 第 3 章   8086 汇编语言程序设计

存放 CPU 寄存器或存储器中暂时不使用的数据 ,

使用数据时将其弹出: PUSH AX ; 将 (AX)入栈

. . .

. . .

11 22

(SP)-2

(SP)-1

(SP)

堆栈段

PUSH AX前

(AX)

. . .

22H

11H

.. .

11H 22H

(SP)

(SP)+1

(SP)+2

堆栈段

PUSH AX后

(AX)

Page 84: 第 3 章   8086 汇编语言程序设计

使用数据时将其弹出:POP BX

. . .

22H

11H

.. .

33H 44H

BX

(SP)

(SP)+1

(SP)+2

堆栈段

POP BX前

. . .

22H

11H

.. .

11H 22H

BX

(SP)-2

(SP)-1

(SP)

堆栈段

POP BX后

Page 85: 第 3 章   8086 汇编语言程序设计

调用子程序(或过程)或发生中断时要保护断点的地址, 子程序或中断返回时恢复断点。

子程序嵌套

. . .

2(L)断点

2(H)断点

1(L)断点

1(H)断点

. . .

(SP)

先压入

后压入

先弹出

后弹出

堆栈段

断点地址压入和弹出情况

主程序

子程序1 子

程序21断点 2断点

弹出2断点弹出

1断点

Page 86: 第 3 章   8086 汇编语言程序设计

注意事项

堆栈是一重要数据结构,使用堆栈应有明确目的。

不乱用堆栈操作,不乱修改堆栈内容。

PUSH 、 POP 、 PUSHF 、 POPF 、

CALL 、 RET 、 INT 、 IRET

乱修改 SS 和 SP 的内容

包括 乱用 BP参与的存储器操作数

乱用指令

Page 87: 第 3 章   8086 汇编语言程序设计

PUSH 和 POP 指令只能对字操作。

PUSH AL

POP BYTE PTR [BX]

可以对段寄存器操作 但 POP 不能对 CS 操作

PUSH DS

PUSH CS

POP ES

POP CS

Page 88: 第 3 章   8086 汇编语言程序设计

自学堆栈应用:比较下边两个程序运行结果?

例:用用 BPBP 的基址指令的基址指令 代替代替 POPPOP 指令指令

…MOV BP,SP

PUSH AXPUSH BXPUSH CX

…MOV CX,[BP-6] MOV BX,[BP-4]MOV AX,[BP-2]

…ADD SP, 6

例 : 压入堆栈的内容压入堆栈的内容与弹出内容顺序相反与弹出内容顺序相反

…PUSH AXPUSH BXPUSH CX

…POP CXPOP BX

POP AX

Page 89: 第 3 章   8086 汇编语言程序设计

( 3) XCHG交换指令 ( 自学 )

格式 XCHG oprd1, oprd2

执行 (oprd1) (oprd2)

reg reg

reg mem

mem reg

可实现

Page 90: 第 3 章   8086 汇编语言程序设计

例 XCHG AX, BX 字操作

执行前( AX ) = 1122H ( BX ) = 3344H

执行后( AX ) = 3344H ( BX ) = 1122H

例 XCHG AH, BL 字节操作

执行前( AX ) = 1122H ( BX ) = 3344H

执行后( AX ) = 4422H ( BX ) = 3311H

Page 91: 第 3 章   8086 汇编语言程序设计

XCHG oprd1, oprd2

注意事项 :

双操作数指令

可进行字或字节操作 , 不影响标志位。

不允许对立即数、段寄存器做操作数

XCHG AX, 4

XCHG BX, DS

• 存储器之间不能交换,两个操作数中必须有一个在寄存器中; XCHG [BX],[DI] ( 错)

Page 92: 第 3 章   8086 汇编语言程序设计

(4 ) XLAT(4 ) XLAT (( Trans lateTrans late )换码指令:)换码指令:该指令不影响标志位。

格式: XLAT str_table ;( AL )←(( BX ) +( AL ))

或 XLAT

str_table—— 表格符号地址(首地址),

只是为了提高可读性而设置,汇编时仍用 BX 。

Page 93: 第 3 章   8086 汇编语言程序设计

XLAT 指令使用方法:

先建立一个字节表格; 表格首偏移地址存入表格首偏移地址存入 BXBX;; 需要转换需要转换代码的序号代码的序号(相对与表格首地址位移量)存入存入 AALL;

(表中第一个元素的序号为 0 ) 执行执行 XLATXLAT 指令后,表中指定序号的元素存于指令后,表中指定序号的元素存于 ALAL 中中。

(AL) 为转换的代码。

Page 94: 第 3 章   8086 汇编语言程序设计

XLATXLAT 指令应用:指令应用:

若把字符的扫描码转换成 ASCII码;

或数字 0~9 转换成 7 段数码所需要的相应代码(字形码)等

就要用 XLAT 指令。

例:内存的数据段中有一张十六进制数字的 ASCII码表。

首地址为: Hex_table ,欲查出表中第 10 个元素(‘ A’)

Page 95: 第 3 章   8086 汇编语言程序设计

执行指令序列:MOV BX , OFFSET Hex_table

MOV AL , 0AH

XLAT Hex_table

假设:

( DS ) =F000H ,

Hex_table=0040H

( AL ) =0AH

执行 XLAT 以后:

( AL ) =41H= ( F004AH ),

即“ A” 的 ASCII码。

30H

31H

32H

...

39H

41H

42H

...

46H

...

Hex_table

Hex_table+1

Hex_table+2

Hex_table+0AH

Hex_table+0BH

Hex_table+0FH 'F'

'B'

'A'

'9'

'1'

'2'

'0'

16 进制数的 ASCII码表

Page 96: 第 3 章   8086 汇编语言程序设计

3. 3. 目的地址传送指令目的地址传送指令( Address-object transfer)

8086 /8088 提供三条 :

地址指针写入指定寄存器或寄存器对指令。

(1) LEA(Load Effective Address)

(2) LDS (Load pointer using DS)

(3) LES (Load pointer using ES)

Page 97: 第 3 章   8086 汇编语言程序设计

(1) LEA 有效地址传送

格式 LEA reg, mem

执行 ( reg ) ← mem 的 EA

即 寄存器 ← 存储器操作数的偏移地址

Page 98: 第 3 章   8086 汇编语言程序设计

执行后 ( BX ) = 1000H

注意:

OFFSET 是汇编程序提供的一个操作符,不是 CPU 的指令 .

LEA BX, buffer

例 buffer 是一个符号地址表示的内存操作数 ( 变量 ) 。

…...12h34h56h…...

buffer

内存

DS: 1000h若变量 buffer 的偏移地址 = 1000H

等价于   MOV BX , OFFSET buffer

Page 99: 第 3 章   8086 汇编语言程序设计

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 为偏移值的内存单元

Page 100: 第 3 章   8086 汇编语言程序设计

LEA reg, mem

特点及注意事项:

目的操作数 reg 应是 16 位通用寄存器 LEA ES, [BX]

LEA AL, buffer

LEA 6, [BX+SI]

LEA [DI], buffer

源操作数应是存储器操作数 LEA BX, AX

传送的是内存单元的有效地址,与其内容无关。

…...12h34h56h…...

buffer

内存

Page 101: 第 3 章   8086 汇编语言程序设计

(2)(2) LDSLDS (Load pointer using DS)

格式: LDS reg16, mem32 ;( reg16 )←( EA )

( DS )←(( EA ) +2 ))

功能 : 把源操作数指定的把源操作数指定的 44 个相继字节送指令指定的寄存器 及个相继字节送指令指定的寄存器 及 DSDS 寄存寄存器中。器中。

前两个单元内容 (16 位偏移量 )装入指定通用寄存器,

后两个单元内容 ( 段地址 ) 装入到 DS 段寄存器。

用于写远地址指针。

Page 102: 第 3 章   8086 汇编语言程序设计

例 :

假设: (DS)=C 000H

指令 : LDS SI, [0010H]

执行指令后 :

(SI)=0180H

(DS)=2000H

80H

01H

00H

20H

C000H:0010H

(DS)

C0011H

C0012H

C0013H

...

...

存储器

Page 103: 第 3 章   8086 汇编语言程序设计

(3)(3) LES (Load pointer using ES)LES (Load pointer using ES)

格式: LES reg16, mem32 ;( reg16 )←( EA )

( ES )←(( EA ) +2 ))

功能:把源操作数指定的把源操作数指定的 44 个相继字节送指令指定的寄存器及个相继字节送指令指定的寄存器及 ESES 寄存器中。寄存器中。

前两个单元内容 (16 位偏移量 )装入指定通用寄存器,

后两个单元内容 ( 段地址 ) 装入到 ES 段寄存器。

此指令常常指定 DI 寄存器。

用于写远地址指针。

Page 104: 第 3 章   8086 汇编语言程序设计

例 :

假设: (DS)=B 000H

(BX)=080AH

指令 : LES DI, [BX]

执行指令后 :

(DI)=05A2H

(ES)=4000H

A2H

05H

00H

40H

B000H:080AH

(DS)

B080BH

B080CH

B080DH

...

...

存储器

(BX)

Page 105: 第 3 章   8086 汇编语言程序设计

4.4. 标志传送指令标志传送指令( Flag register transfer )

采用了隐含寄存器( AH 、 Flags) 操作数方式。

8088 有四条标志传送操作指令:(1) . LAHF ( Load AH into flags )

(2) . SAHF ( Store AH into flags )

(3) . PUSH F ( Push flags onto stack )

(4) . POP F ( Pop flags off stack )

Page 106: 第 3 章   8086 汇编语言程序设计

(1)(1) .. LAHFLAHF ( Load AH flags flags )格式: LAHF ;( AH )←( PSW 的低字节)

功能:标志寄存器低八位 标志寄存器低八位 (( AHAH ))。

SF ZF AF PF CF

01234567

TFIFDFOF

89101112131415

01234567

FLAGS

AH

LAHF 指令操作图示意

Page 107: 第 3 章   8086 汇编语言程序设计

(2) . SAHF ( Store AH into flags )

格式: SAHF ;( PSW 的低字节)←( AH )

功能:( AH )送标志寄存器低八位。

SFZF AF PF CF

01234567

TFIFDFOF

89101112131415

01234567

FLAGS

AH

Page 108: 第 3 章   8086 汇编语言程序设计

SS:SP

SS:SP (PSW)

(4). POPF 标志出栈格式 POPF

执行 ( PSW )← ( SS : SP ) ( SP ) ← ( SP ) + 2

SS:SP

SS:SP (PSW)

(3). PUSHF 标志入栈格式 PUSHF

执行 ( SP ) ← ( SP ) - 2

( SS : SP ) ← ( PSW )

Page 109: 第 3 章   8086 汇编语言程序设计

特点及注意事项:

无操作数的形式,操作数隐含为 ( PSW)

PUSHF AX

POPF CX

PUSHF 和 POPF 用于标志信息的保存和恢复

Page 110: 第 3 章   8086 汇编语言程序设计

注意:

( 1 ) 标志位的影响

LAHF 、 PUSHF 不影响标志位 ,

SAHF 、 POPF 由装入的值确定标志位的值, 即影响标志位。

( 2 ) PUSH F 、 POPF 用于保护调用过程前( PSW), 过程返回后恢复。例: …

PUSH AX

PUSH CX

PUSH F

CALL TRANS

POPF

POP CX

POP AX

Page 111: 第 3 章   8086 汇编语言程序设计

三 . 算术运算指令

二进制运算 十进制调整

加 ADD, ADC, INC AAA, DAA

减 SUB, SBB, DEC, NEG, CMP AAS, DAS

乘 MUL, IMUL AAM

除 DIV, IDIV AAD

符号扩展指令: CBW、CWD

指令分类:

Page 112: 第 3 章   8086 汇编语言程序设计

特点: 带符号数用补码表示 如 MOV AX, -1 等价于 MOV AX, 0FFFFh

对加、减运算,不区分无符号数、带符号数 (参见第一章例)

对乘、除运算,区分无符号数、带符号数 可进行字节或字操作 影响状态标志 十进制运算方法 ( 不做重点,讲义中做了简单介绍 )

( 讲义最后提供十进制运算的自学内容)当数据用压缩或非压缩 BCD码表示时,为使运算的结果仍为 BCD码表示,需对结果进行调整。 十进制运算 = 二进制运算 + 十进制调整

Page 113: 第 3 章   8086 汇编语言程序设计

十进制数码 0 1 2 3 4

8421 BCD码 0000 0001 0010 0011 0100

十进制数码 5 6 7 8 9

8421 BCD码 0101 0110 0111 1000 1001

BCD码( Binary Coded Decimal )

用二进制编码表示十进制数。 常用 8421 BCD码 , 与十进制数码对应关系:

例 48 的 BCD码为 ( 0100 1000 ) BCD

Page 114: 第 3 章   8086 汇编语言程序设计

根据在内存的存放形式,分压缩 BCD码和非压缩 BCD码

压缩压缩 BCDBCD码码( Packed BCD format ) 用用 44 位二进制数表示一个十进制数位位二进制数表示一个十进制数位,一字节存放 2 个 BCD码。

整个十进制数形式为一个顺序的 4 位为一组的数串。

例: 9502d 的压缩 BCD码应表示为:

9 5 0 2

非压缩非压缩 BCDBCD码码( Unpacked BCD format ) 用用 88 位为一组表示一个十进制数位,位为一组表示一个十进制数位,一字节存放 1 个 BCD码。

8 位中的低 4 位表示 8421 的 BCD码,而高而高 44 位没有意义位没有意义。

例: 9502d 的非压缩 BCD码则表示为:

9 5 0 2

1 0 0 1 0 1 0 1 0 0 0 0 0 0 1 0

1 0 0 1 0 1 0 1 0 0 0 0 0 0 1 0

Page 115: 第 3 章   8086 汇编语言程序设计

ASCIIASCII 码是一种非压缩码是一种非压缩 BCDBCD 码码数字的 ASCII 的高 4 位 0011 无意义;

低 4 位是以 8421码形式表示的十进制数位。

符合非压缩 BCD码高 4 位无意义的规定。

2 的 ASCII码:

高 4 位 0011 无意义

0 0 1 1 0 0 1 0

Page 116: 第 3 章   8086 汇编语言程序设计

当数据用压缩或非压缩 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

Page 117: 第 3 章   8086 汇编语言程序设计

1. 加法运算指令

指令格式 执 行 操 作

ADD dst, src (dst) ← (dst) + (src)

ADC dst, src (dst) ← (dst) + (src) + CF

INC oprd (oprd) ← (oprd) + 1

ADD 、 ADC 为双操作数指令 INC 为单操作数指令 除 INC 指令不影响 CF 外,其余指令 6 个状态标志均据结果置位

ADC 带进位加法,实现字以上运算(进位是上条指令运算的进位)

OF DF IF TF SF ZF AF PF CF

Page 118: 第 3 章   8086 汇编语言程序设计

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 , 0CFA1HADD DX , 62A0H

执行后 :( DX ) =3241H CF=1 , OF=0 , SF=0 , ZF=0

(注意: CF 和 OF 的判断方法 )

Page 119: 第 3 章   8086 汇编语言程序设计

OF=1OF=1, 8 位带符号数相加,和超出范围(- 128~+ 127 ) ,

16 位带符号数相加,和超出范围 (-32768~+32767);

加法:两个正数相加,结果为负;或两个负数相加,结果为负。

( 两个异号数相加不可能溢出)

减法: 两个异号数相减,结果与减数相同。

( 两个同号数相加不可能溢出)

运算结果错误。

CF=1CF=1, 8 位无符号数相加,和超过 255 ,

16 位无符号数相加,和超过 65535 。 运算结果准确

其他条件标志( SF,AF,PF,ZF) 根据定义设定。

Page 120: 第 3 章   8086 汇编语言程序设计

D:\MASM> DEBUG-A ; 汇编指令1270:0100 MOV AX, CFA11270:0103 ADD AX, 62A01270:0106-R ; 执行前查看各寄存器内容AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=1270 ES=1270 SS=1270 CS=1270 IP=0100 NV UP EI PL NZ NA PO NC1270:0100 B8A1CF MOV AX,CFA1-T 2 ; 执行汇编的两条指令 , 并查看执行后的结果…...AX=3241 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=1270 ES=1270 SS=1270 CS=1270 IP=0106 NV UP EI PL NZ NA PE CY1270:0106 57 PUSH DI-

利用 DEBUG 学习加法指令

Page 121: 第 3 章   8086 汇编语言程序设计

三组指令执行后的结果均为:(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计算时不区分无符号数、带符号数

Page 122: 第 3 章   8086 汇编语言程序设计

例 2 加 1 指令 : INC AL

  执行前 ( AL ) = FFH

执行后 :

( AL ) =00H

CF= 不变, OF=0 , ZF=1 , SF=0

FFH

+ 01H

11

00H

Page 123: 第 3 章   8086 汇编语言程序设计

01FFH+ 0001H进位 11 0200H

例 3 value 是一个字变量   OFFSET value = 1000H

 ( DS ) =2000H ,( 21000H ) =01FFH

value FF21000H 01

执行前

value 0021000H 02

执行后执行后:  ( 21000H ) =0200H

CF= 不变, OF=0 , ZF=0 , SF=0

注意: INC value 是内存单元内容加 1 ,而非地址加 1

INC value

或写成 :

INC [value]

Page 124: 第 3 章   8086 汇编语言程序设计

例 4 将 buffer 为首的 4 个字节内存内容相加,存放在 AL 中。

buffer 1AB7C5D6

注意若编程如下 ,MOV CX, 4MOV AL, 0

exit: ADD AL, [buffer] INC buffer DEC CX

JNZ exit 

不能实现 , 为什么?

…... MOV CX, 4 LEA BX, buffer

MOV AL, 0exit: ADD AL, [BX]

INC BX DEC CX JNZ exit

实现的 是 (1A)+(1B)+(1C)+(1D)指令 INC buffer 将 buffer 指向的内容加 1 ,而不是地址 buffer 加 1

Page 125: 第 3 章   8086 汇编语言程序设计

例 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 只能按字节或字相加。 位数在字以上的操作数,先加低位,再加高位, 加高位时加入从低位产生的进位。

Page 126: 第 3 章   8086 汇编语言程序设计

用途举例计算两个多字节数相加 3B74AC60F8H+20D59E36C1H=?两个多字节数存放在:DATA1,DATA2 的开始单元。

F8H

60H

ACH

74H

3BH

.. .

C1H

36H

9EH

D5H

20H

.. .

DATA1

DATA2

流程图多字节数内存存放

开始

CX初始化,置循环次数SI CF清 、

取一个字节加数

取一个被加数字节相加送内存

SI)+1 SI)( 送(

(CX)-1 (CX)送

(CX)=?0

结束

N

Y

Page 127: 第 3 章   8086 汇编语言程序设计

程序:MOV CX, 5MOV SI, 0 ; 清 SICLC ;清 CF

LOOPER: MOV AL, DATA2[SI]ADC DATA1[SI],ALINC SI ;(SI)+1 (SI)DEC CX ;(CX)-1 (CX)JNZ LOOPER ;(CX)0 转HLT ;停机

Page 128: 第 3 章   8086 汇编语言程序设计

问题思考问题思考: ( 1 )什么叫溢出?什么溢出?什么叫进位?进位?

( 2 )有进位就有溢出,没有进位就没有溢出?有进位就有溢出,没有进位就没有溢出?

( 1 ) 溢出溢出 ------------ 是指是指带符号数的补码溢出。溢出。 字长为 字长为 n n 位位带符号数,补码运算能表示范围为 : -2 n-1 ~+2 n+1 –1

如果运算结果超出该范围,叫补码溢出,简称溢出。溢出,简称溢出。

在溢出时,在溢出时,造成造成运算错误。

进位进位 ------------ 是指是指运算结果的最高位向更高位的进位。进位。

有进位,有进位, CF=1CF=1;无进位, ;无进位, CF=0CF=0

Page 129: 第 3 章   8086 汇编语言程序设计

(( 22 ))有进位就有溢出,没有进位就没有溢出?有进位就有溢出,没有进位就没有溢出?

结论:结论: 有进位不一定有溢出 ,没有进位不一定没有溢出。

数的表示范围:• 8 位二进制数可以表示十进制数的范围:

8 位带符号十进制数的范围:- 128~+ 127

8 位无符号十进制数的范围: 0~ 255

• 16 位二进制数可以表示十进制数的范围 :

16 位带符号十进制数的范围:- 32768~+ 32767

16 位无符号十进制数的范围: 0~ 65535

Page 130: 第 3 章   8086 汇编语言程序设计

以 8 位二进制数为例分析一下数的溢出与进位情况:

下面分 4 种情况加以讨论:

( 1 )带符号数和无符号数都不溢出

( 2 )无符号数溢出

( 3 )带符号数溢出

( 4 )带符号数和无符号数都溢出

Page 131: 第 3 章   8086 汇编语言程序设计

(( 11 ))带符号数和无符号数都不溢出带符号数和无符号数都不溢出。二进制数 看作无符号数 看作带符号数

0 0 0 0 0 1 0 0

0 0 0 0 1 0 1 1+

0 0 0 0 1 1 1 1

4

11+

15

+ 4

+1 1+

+1 5

相加

标志 CF=0,OF=0 CF=0 OF=0

溢出 不溢出 不溢出

不溢出同符号数相加,结果符号与其相同

Page 132: 第 3 章   8086 汇编语言程序设计

(( 22 ))无符号数溢出无符号数溢出

二进制数 看作无符号数 看作带符号数

0 0 0 0 0 1 1 1

1 1 1 1 1 0 1 1+

0 0 0 0 0 0 1 0

7

251+

258

+ 7

- 5+

+ 2

相加

标志 CF=1,OF=0 CF=1 OF=0

溢出 无符号数溢出 溢出结果应为 2 ,错

不溢出异号数相加

不可能有溢出

CF=1

Page 133: 第 3 章   8086 汇编语言程序设计

(( 33 ))带符号数溢出带符号数溢出

二进制数 看作无符号数 看作带符号数

0 0 0 0 1 0 0 1

0 1 11 1 1 1 0 0+

1 0 0 0 0 1 0 1

9

124+

133

+ 9

+1 2 4+

+1 3 3

相加

标志 CF=0,OF=1 CF=0 OF=1

溢出 带符号数溢出 不溢出

溢出 123结果为-

结果错

Page 134: 第 3 章   8086 汇编语言程序设计

(( 44 ))带符号数和无符号数都溢出带符号数和无符号数都溢出

二进制数 看作无符号数 看作带符号数

1 0 0 0 0 1 1 1

1 1 1 1 0 1 0 1+

0 1 1 1 1 1 0 0

135

245+

380

121-

- 11+

132-

相加

标志 CF=1,OF=1 CF=1 OF=1

溢出 无符号数溢出溢出

现结果为124,结果错

溢出124现结果为 ,

结果错

CF=1

Page 135: 第 3 章   8086 汇编语言程序设计

结论结论::

( 1 )带符号数相加溢出

根据 OF= 1 ? , 判断带符号数产生溢出?

OF=1OF=1 ,同符号数相加,结果符号与其相反,,同符号数相加,结果符号与其相反,产生溢产生溢出出;;

OF=0, OF=0, 同符号数相加,结果符号与其相同,不同符号数相加,结果符号与其相同,不产生溢出产生溢出;;

异号数相加,异号数相加,不可能溢出。不可能溢出。

( 2 )无符号数相加溢出根据 CF= 1 ? , 判断无符号数产生溢出?CF=1,CF=1, 无符号数无符号数相加相加产生溢出产生溢出 ,,但结果并没有错,但结果并没有错,只是结果放不下。只是结果放不下。

Page 136: 第 3 章   8086 汇编语言程序设计

指令格式 执行操作 SUB dst, src (dst) ← (dst) - (src)

SBB dst, src (dst) ← (dst) - (src) - CF

DEC oprd (oprd) ← (oprd) - 1

NEG oprd (oprd) ← 0 - (oprd)

CMP oprd1, oprd2 (oprd1) - (oprd2)

2. 减法运算指令

SUB 、 SBB 、 CMP 为双操作数, DEC 、 NEG 为单操作数 SBB 为带进位减法(进位是上条指令运算的进位)。 除 DEC 不影响 CF 标志外,其余指令 6 个状态标志均据结果置位。 NEG求补运算,等价于用 0 减去操作数。

其对标志位的影响,由 0 减去该操作数的过程决定。

Page 137: 第 3 章   8086 汇编语言程序设计

例 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 , 2D04HSUB AX , 3AB0H

借位

Page 138: 第 3 章   8086 汇编语言程序设计

例 2 带进位减法: 用指令完成两双字相减运算

0546 7A70H - F001 A543H

MOV AX , 7A70H

SUB AX , A543H

MOV BX , 0546H

SBB BX , 0F001H

Page 139: 第 3 章   8086 汇编语言程序设计

例 3 减 1 指令: value 是一个字节变量

OFFSET value = 1000H

( DS ) =2000H ,( 21000H ) =00H

DEC value

执行后:( 21000H ) =0FFH

CF= 不变, OF=0 , ZF=0 , SF=1

注意: DEC value 是内存单元内容减 1 ,而非地址减 1

00 H - 01 H 11

FFH

Page 140: 第 3 章   8086 汇编语言程序设计

例 4 求补指令: 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

Page 141: 第 3 章   8086 汇编语言程序设计

例 5 :求绝对值

在内存中,从 AREA1开始存放100 个带符号数。

求各数的绝对值存于AREA2 的开始单元。

流程图

开始

初始化置源地址,置目的地址指针

置循环次数

取一个带符号数

负数?

求补

送存

1地址指针+

1循环次数-

0循环次数= ?

结束

N

Y

N

Y

Page 142: 第 3 章   8086 汇编语言程序设计

程序:LEA SI, AREA1LEA DI, AREA2MOV CX, 100

CHECK: MOV AL, [SI]OR AL, AL ;(AL) 内容不变,置标志JNS NEXT ; SF=0 转 NEXTNEG AL ;负数求补

NEXT: MOV [DI], AL ;送目标INC SIINC DIDEC CXJNZ CHECKHLT

Page 143: 第 3 章   8086 汇编语言程序设计

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 ,进行两操作数相减操作, 但只影响标志值,不影响操作数 ( 减的结果不保存 )

比较指令:

Page 144: 第 3 章   8086 汇编语言程序设计

条件转移指令 判断条件

低于 JB next CF = 1

低于或等于 JBE next CF = 1 或 ZF = 1

高于 JA next CF = 0 且 ZF = 0

高于或等于 JAE next CF = 0

CMP AX, BX ;比较 JAE above ;高于或等于则跳转 XCHG AX, BX ;低于则交换

above: 、、、

例 将 AX 和 BX 中较大的无符号数,存于AX 中

比较指令常常根据条件(标志)转移,无符号数转移指令如下:

Page 145: 第 3 章   8086 汇编语言程序设计

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 ,溢出情况,( 由符号位可决定是否溢出 )

Page 146: 第 3 章   8086 汇编语言程序设计

结合 ZF, 得到结论 :

SF OF

00

01

10

11

SF∨ OF 0 1 1 1

或运算:有 1则 1,全 0则 0

逻辑运算:

CMP A, B 两数关系

SF ∨ OF = 0 A≥ B

SF ∨ OF = 1 A<B

(SF ∨ OF) ∨ ZF =0 A>B

(SF ∨ OF) ∨ ZF=1 A≤ B

思考:可否只用 ZF 和 SF判断两符号数关系?

SFOF

00

01

10

11

SF∨ OF 0 1 1 0

异或运算: 异则 1,同则 0

Page 147: 第 3 章   8086 汇编语言程序设计

条件转移指令 判断条件

小于 JL next SF ∨ OF = 1

小于或等于 JLE next ( SF ∨ OF)∨ZF=1

大于 JG next ( SF ∨ OF)∨ZF =0

大于或等于 JGE next SF ∨ OF=0

例 将 AX 和 BX 中较大的带符号数,存于 AX 中

CMP AX, BX ;比较 JGE great ;大于或等于则跳转 XCHG AX, BX ;小于则交换

great: 、、、

比较指令常常根据条件(标志)转移,带符号数转移指令如下:

Page 148: 第 3 章   8086 汇编语言程序设计

CMP 指令应用举例:带符号数带符号数找最大值 找最大值 (( 自学自学 P40~P40~4141 )) 若自 BLOCK开始的内存缓冲区中,有 100 个带符号数。

找出最大值。并存放到 MAX 单元中。

思路:思路:• 第一个数取出 ( AX) , • 取出第二个数(第二个字单元内容)与 (AX)比较 :

( AX ) >第二个数,不做交换,

否则,(第二个字单元内容) ( AX )。

• 再取第三个数,

• 经过 99次比较,在( AX )中得到最大数。

Page 149: 第 3 章   8086 汇编语言程序设计

编程: … MOV BX , OFFSET BLOCK

MOV AX , [BX]

INC BX

INC BX

MOV CX , 99

AGAIN : CMP AXCMP AX ,, [BX][BX]

JG NEXTJG NEXT ; (AX) >(16d(ds)+(BX)) 转 NEXT MOV AX , [BX]

NEXT: INC BX

INC BX

DEC CX

JNE AGAIN

MOV MAX , AX ; MAX 单元存放最大值…

Page 150: 第 3 章   8086 汇编语言程序设计

3. 乘法指令

指令格式 执行操作

MUL src

若 src为字节类型: (AX) ← (AL)× (src) 若 src为字类型: (DX),(AX) ← (AX)× (src)

将被乘数、乘数看作无符号数,进行乘运算 乘的结果也为无带符号数

IMUL src 执行的操作与MUL相似 将被乘数、乘数看作带符号数, 进行乘运算 乘的结果也为带符号数

无符号数乘法

带符号数乘法

Page 151: 第 3 章   8086 汇编语言程序设计

MUL src

IMUL src

单操作数指令 源操作数 ( 乘数 ) 类型决定操作类型 目的操作数 ( 被乘数 ) 隐含。 字节乘 AL 字乘 AX

字节相乘的结果存放在 AX 中 字相乘的结果存放在 DX 、 AX 中 MUL 用于无符号数运算 IMUL 用于带符号数运算

Page 152: 第 3 章   8086 汇编语言程序设计

影响 CF 和 OF ,对其他条件码无定义(不确定)

( 1 )指令 MUL

字节相乘, AH=0 , CF=OF=0 ,否则 CF=OF=1

字相乘, DX=0 , CF=OF=0 ,否则 CF=OF=1

即:即: 积的高一半为积的高一半为 00 (字节乘((字节乘( AHAH )) =0=0 ,字乘(,字乘( DXDX )) =0=0 ),),

则则 CF=0CF=0 ,, OF=0OF=0 ;否则;否则 CF=1CF=1 ,, OF=1OF=1 。。

对其它条件码不确定(无定义)。状态不定。状态不定。

Page 153: 第 3 章   8086 汇编语言程序设计

( 2 )指令 IMUL

字节相乘, AH=0 或 AH=FFH , CF=OF=0 ,否则 CF=OF=1

字相乘, DX=0 或 DX=FFFFH , CF=OF=0 ,否则 CF=OF=1

即:即:积的高一半为低一半的符号扩展积的高一半为低一半的符号扩展 ,, 则 则 CF=0CF=0 ,, OF=0OF=0 ;;

积的高一半部分不是低一半部分符号的扩展积的高一半部分不是低一半部分符号的扩展

( 包括结果的有效数字,不光是符号部分)( 包括结果的有效数字,不光是符号部分) , , 则 则 CF=1,CF=1,OF=1OF=1 。。

积的高一半为低一半的符号扩展的含义:

乘积为正乘积为正,则则 (AH)=00H(AH)=00H 或(或( DX)=0000HDX)=0000H

乘积为负乘积为负,则则 (AH)=FFH(AH)=FFH 或(或( DX)=FFFFHDX)=FFFFH

Page 154: 第 3 章   8086 汇编语言程序设计

问题思考问题思考:乘法中为什么要用 MUL , IMUL 指令 ?

例 :

结论结论:带符号数相乘,必须使用带符号数相乘,必须使用 IMULIMUL 指令指令无符号数相乘, 必须使用无符号数相乘, 必须使用 MULMUL 指令指令否则,出错。否则,出错。

无符号数 带符号数

(AL)=3

(BL)= ( -2 )

0 0 1 1

× 1 1 1 0

0 0 1 0 1 0 1 0 = 2AH

MUL BL;3×(-2)= -6结果 2AH 是错误

IMU BL ;3×(-2)=(-6) [-2] 求补= 0010

0 0 1 10 0 1 0×

0 0 0 0 0 1 1 0 = 6

[00000110] 求补 = 11111010 = [-6]补

Page 155: 第 3 章   8086 汇编语言程序设计

例 (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

Page 156: 第 3 章   8086 汇编语言程序设计

例 (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

Page 157: 第 3 章   8086 汇编语言程序设计

4. 除法指令 ( 自学 )

指令格式 执行操作

DIV src

无符号数除法

(src)为字节类型:

(AL) ← (AX) / (src) 的商

(AH) ← (AX) / (src) 的余数

(src)为字类型:

(AX) ←DX) , (AX) / (src) 的商

(DX) ←(DX) , (AX) / (src) 的余数

将被除数、除数看作无符号数,进行除法运算,

商、余数也为无符号数

IDIV src

带符号数除法

执行的操作与DIV相同,

将被除数、除数看作带符号数,进行除法运算

商、余数也为带符号数,余数的符号与被除数同

Page 158: 第 3 章   8086 汇编语言程序设计

单操作数指令 源操作数 ( 除数 ) 类型 决定指令操作类型 目的操作数 (被除数 ) 隐含 字节操作在 AX 中;字操作在 DX, AX 中 除的结果,字节操作在 AX 中;字操作在 DX, AX中 除法指令对所有条件码位均无定义 下列情况自动转入 0 中断处理: (1) 除数为 0

(2) 字节操作,商的范围超出字节范围 字操作时,商的范围超出字范围

Page 159: 第 3 章   8086 汇编语言程序设计

除法指令举例

例 (AX)=0501H , (BL)=0C6H

(1) DIV BL (2) IDIV BL

看作无符号数 看作带符号数 (AL) = 1281D (AL) = 1281D

(BL) = 198D (BL) = -58D

1281/198 1281/ (-58)

商 = 6D 商 = -22D=0EAH

余数 =93D=5DH 余数 =5D

执行 DIV BL 后: 执行 IDIV BL 后: (AX) = 5D06H (AX) = 05EAH

Page 160: 第 3 章   8086 汇编语言程序设计

5. 符号扩展指令 ( 自学 )

指令格式 执行操作

CBW

将 (AL) 的符号扩展到 AH 中

(AL)的 D7=0,(AH)=00H

D7=1 ,(AH) =FFH

CWD

将 (AX) 的符号扩展到 DX 中

(AX)的 D15=0,(DX)=0 000H

D15=1 ,

(DX) =FFFFH

Page 161: 第 3 章   8086 汇编语言程序设计

无操作数格式 操作数隐含

字节操作,源在 AL ,目的在 AX字 操 作,源在 AX ,目的在 DX,AX

对条件码无影响 符号扩展指令应对带符号数操作 扩展后,表示的数值大小不变,只是位数发生变化 8 位扩展到 16 位 , 16 位扩展到 32 位 应用场合: 除法指令中,使被除数满足要求。

字节操作,被除数为 16 位 字操作,被除数为 32 位

加减运算中,使两操作数类型一致如:字与字节相加、减时

如:双字与字之间的相加、减时

Page 162: 第 3 章   8086 汇编语言程序设计

符号扩展指令举例例 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 。

Page 163: 第 3 章   8086 汇编语言程序设计

66 、调整指令(自学,一般了解)、调整指令(自学,一般了解)前面提到的所有算术运算指令都是二进制的运算指令,

但人们常用的是十进制。

当用计算机进行计算时:

必须先把十进制十进制 二进制数, 二进制数,

计算结果计算结果 十进制数输出。 十进制数输出。

为便于十进制运算,计算机提供了一组十进制调整指令,

这组指令在二进制基础上给予十进制调整二进制基础上给予十进制调整,,直接得到十进制数直接得到十进制数。

8088 中提供了六条调整指令。

Page 164: 第 3 章   8086 汇编语言程序设计

80888088 中有六条调整指令:中有六条调整指令:( 1 )、 DAA ( Decimal adjust for addition) 加法十进制调整指令

( 2 )、 DAS ( Decimal adjust for subtration) 减法十进制调整指令

( 3 )、 AAA ( ASCII adjust for addition) 加法 ASCII 调整指令

( 4 )、 AAS ( ASCII adjust for subtration) 减法 ASCII 调整指令

( 5 )、 AAM ( ASCII adjust for multiply) 乘法 ASCII 调整指令

( 6 )、 AAD ( ASCII adjust for division) 除法 ASCII 调整指令

共同点:• 调整指令后边不跟操作数调整指令后边不跟操作数::

十进制调整指令隐含寄存器操作数 AL;

ASCII 调整指令隐含寄存器操作数 AL 或 AH 。• 调整对象调整对象:: 十进制调整指令对压缩 BCD 码进行调整;

ASCII 调整指令对非压缩 BCD 码进行调整,

Page 165: 第 3 章   8086 汇编语言程序设计

11 、、 DAADAA ( Decimal adjust for addition) 加法十进制调整指加法十进制调整指令令

格式: DAA条件:参加运算数(加法)必须是两个压缩的参加运算数(加法)必须是两个压缩的 BCDBCD 码, 码, 在执行在执行 DAADAA 指令以前必须执行指令以前必须执行 ADDADD 或或 ADCADC 指令。指令。

功能:( AL )←把由二个组合的 BCD 码相加后的结果(结果一定放在 (AL) 中的),调整到压缩 BCD 格式。

DAA 指令影响 标志 : A 、 C 、 P 、 S 、 Z .

而对 O 标志未作定义。

校正操作: 若 若 (AL)(AL)33 ~~ 00 >9 >9 或或 AF=1, AF=1, 则 则 (AL) (AL) (AL)+6, AF (AL)+6, AF 11

若若 (AL)(AL)77 ~~ 44 >9H >9H 或或 CF=1, CF=1, 则 则 (AL) (AL) (AL)+60H, CF (AL)+60H, CF 11

Page 166: 第 3 章   8086 汇编语言程序设计

应用举例:

例 1: 设( AL ) =28 H ,( BL ) =68H

ADD AL , BL ; ( AL ) =90H , CF=0 , AF=1

DAA ; (AL) (AL)+06 ,(AL) = 96H

; CF=0, AF=1CF=0, AF=1

例 2 : ( BCD3 )←( BCD1 ) + ( BCD2 )= 1834H+ 2789H

= 4623H

注意:

例 2 中的““ H”H” 是为了十进制数能输入而设置。实际是十进制是为了十进制数能输入而设置。实际是十进制数数。

Page 167: 第 3 章   8086 汇编语言程序设计

实现: (BCD1+1)(BCD1)+(BCD2+1)(BCD2)(BCD3+1)(BCD3)

程序 : (( 自学)自学)

MOV AL , BCD1 ;( AL ) =34

ADD AL , BCD2 ;( AL )←( AL ) + ( BCD2 ) ,BD=34+89 , AF=0 ,CF=0

DAA ; 0BD+06+60=23, AF=1 , CF=1

MOV BCD3 , AL ; ( BCD3 ) =23

MOV AL , BCD1+1 ; ( AL ) =18

ADC AL , BCD2+1 ; 40=18+27+CF→ ( AL ) ,AF=1 , CF=0

DAA ;( AL ) +06=46→ ( AL ) , CF=0 , AF=1

MOV BCD3+1 , AL ; ( BCD3 ) = 4623H

;( BCD3+1 ) ( BCD3 ) = 4623H

Page 168: 第 3 章   8086 汇编语言程序设计

(( 22 )、)、 DASDAS ( Decimal adjust for subtration) 减法十进制调整减法十进制调整指令指令

格式: DAS

操作 : (AL)← 把( AL )中的差调整到压缩的 BCD 格式。

条件:参加运算的数参加运算的数 (( 两个两个 BCDBCD 码码 )) 必须紧跟在必须紧跟在 SUBSUB 或或 SBBSBB 指指令以后。令以后。

DAS 影响 标志 : 影响 A 、 C 、 P 、 S 、 Z .而对 O 标志未作定义。

校正操作:

若 若 (AL)(AL)33 ~~ 00 >9 >9 或或 AF=1,AF=1, 则 则 (AL) (AL) (AL)(AL) -- 6, AF 6, AF 11

若若 (AL) (AL) 77 ~~ 4 4 > 9 > 9 或或 CF=1, CF=1, 则 则 (AL) (AL) (AL)(AL) -- 60H, CF 60H, CF 11

Page 169: 第 3 章   8086 汇编语言程序设计

应用举例:例 1 :设( AL ) =86H , ( AH ) =07H

SUB AL , AH ;( AL ) =7FH , CF=0 , AF=1

DAS ;( AL ) = ( AL ) -06=79 H ,

例 2 :设( BCD1 ) =1234H ,( BCD2 ) =4612H (自学)(自学)

试写出( BCD3 )←( BCD1 ) - ( BCD2 )指令序列。

MOV AL , BCD1 ;( AL ) =34

SUB AL , BCD2 ;( AL )←( AL ) - ( BCD2 ) =34-12=22

DAS ;( AL ) =22 ,未作调整未作调整

MOV BCD3 , AL ;( BCD3 )← 22

MOV AL , BCD1+1 ;( AL )←( BCD1+1 ) =12

SBB AL , BCD2+1 ;( AL )←( AL ) - ( BCD2+1)-CF =12—46=CCH,

DAS ;( AL )←( AL ) -06-60=66 , AF=1,CF=1

MOV BCD3+1 , AL ;( BCD3+1 )←( AL ) =66

6622 是 -3378 的十的补码(以十为模 ) 结果对的

Page 170: 第 3 章   8086 汇编语言程序设计

(( 33 )、)、 AAAAAA ( ASCII adjust for addition) 加法加法 ASCIIASCII 调整调整指令指令

格式: AAA

执行操作执行操作:( AL )把( AL )中的和调整到非压缩和调整到非压缩 BCDBCD 格格式式。

( AH )( AH ) + 调整产生的进位值。

条件:条件:参加运算的数必须是两个非压缩参加运算的数必须是两个非压缩 BCDBCD 码,指令必须紧跟 码,指令必须紧跟 在 在 ADDADD 、、 ADCADC 指令以后,相加结果必须在(指令以后,相加结果必须在( ALAL )中。)中。

指令调整步骤:指令调整步骤:

• 如(如( ALAL )) 00 ~~ 33=0=0~~ 99且且 AF=0AF=0 ,则(,则( ALAL )) 4--7 4--7 00 ,, AFAFCFCF

• 如(如( ALAL )) 00 ~~ 33=A~F =A~F 或 或 AF=1AF=1 ,则(,则( ALAL ) ) ( ( ALAL )) +0+0

66 ,,

(( AHAH ) ) ( ( AHAH )) +1+1 ,,

(( ALAL )) 4-~7 4-~7 0 0 ,, AF AF CF CF

影响标志位:影响标志位:影响 AF 、 CF ,其它标志位均无定义。

Page 171: 第 3 章   8086 汇编语言程序设计

应用举例:

例 1 : 设( AX ) =0535H ,

( BL ) =39H

程序:

ADD AL,BL

;( AL ) =6EEH , AF=0, (AH)=05H

AAA AAA

;( AX ) =06060404H , AF=1AF=1 ,, CF=1CF=1

例 2 :计算 4609+ 3875 =?(自学)

加数与被加数存放在内存情况如右图:

39

30

36

34

.. .

35

37

38

33

.. .

. . .

SUM

STRING2

STRING1 ' 9'

' 0'

' 6'

' 4'

' 5'

' 7'

' 8'

' 3'

被加数

加数

存结果

加数与被加数存放在内存情况

Page 172: 第 3 章   8086 汇编语言程序设计

程序:LEA SI, STRING1LEA BX, STRING2LEA DI, SUMMOV CX,4CLC

NEXT:MOV AL, [SI]ADC AL, [BX]AAAAAAMOV [DI], ALINC SIINC BXINC DIDEC CXJNZ NEXTHLT

流程图

开始

初始化,置被加数、加数、结果的地址指针

置循环次数,清进位

取一个字节被加数

与加数相加

AAA调整

送存

1地址指针+

1循环次数-

0循环次数= ?

结束

N

Y

Page 173: 第 3 章   8086 汇编语言程序设计

(( 44 )、)、 AASAAS ( ASCII adjust for subtration) 减法减法 ASCIIASCII 调整指调整指令令

格式: AAS

执行操作执行操作:( AL ) 把( AL )中的差调整到非压缩差调整到非压缩 BCDBCD 格式格式,

(( AHAH ))(( AHAH )) -- 调整产生的借位值调整产生的借位值

条件:条件:参加运算的数,必须是两个非压缩参加运算的数,必须是两个非压缩 BCDBCD 码,码,

这条指令必须紧跟在这条指令必须紧跟在 SUBSUB 或或 SBBSBB 指令以后。指令以后。

调整步骤:调整步骤:

• 如(如( ALAL )) 0~30~3=0~9=0~9且且 AF=0AF=0 ,则(,则( ALAL )) 4~7 4~7 00 ,, CF CF AFAF

• 如(如( ALAL )) 0~30~3=A~F=A~F 或或 AF=1AF=1 ,则(,则( ALAL ) ) ( ( ALAL )) -06-06 ,,

(( AHAH ) ) ( ( AHAH )) -1, AF -1, AF 1 1

(( ALAL )) 4~7 4~7 0 0 ,, CF= AF=1CF= AF=1

影响标志位:影响 AF 、 CF ,其它标志位均无定义。

Page 174: 第 3 章   8086 汇编语言程序设计

例: 编写程序段,实现 (DX)←UP1+UP2-UP3 = 25 + 48 -19 (( 自学)自学)

每位十进制数以非压缩每位十进制数以非压缩 BCDBCD 格式存入存储器,每个数占一个字。格式存入存储器,每个数占一个字。MOV AX , 0 ;(( AHAH )) =0=0

MOV AL , UP1 ; ( AL )← 05H

ADD ALADD AL ,, UP2UP2 ; ( AL )← 05+08=0DDH

AAA AAA ; ( AL )← 0D+06=03H0D+06=03H , AF=1AF=1 ,(( AHAH )←()←( AHAH )) +1=01H +1=01H ,, CF=1←AF=1CF=1←AF=1

MOV DL,AL ; ( DL )← 03H

MOV AL , UP1+1 ; ( AL ) =02 H

ADC AL,UP2+1ADC AL,UP2+1 ;( AL )← 02+04+CFCF=06+1=07 , AF=0 , CF=0

AAA AAA ;( AL ) =07 , CF=AF=0 未调整未调整

XCHG AL , DL ;( DL ) =07 ,( AL ) =03

SUB ALSUB AL ,, UP3UP3 ;( AL )←( AL ) - ( UP3 ) =03-09=0AA , AF=1AF=1

AAS AAS ;( AL )←( AL ) -0606=04H , CF=AF=1CF=AF=1 ,(,( AHAH )←()←( AHAH )) -1=0-1=0

XCHG AL , DL ;(( DLDL )) =04H=04H ,( AL ) =07H

SBB ALSBB AL ,, UP3+1UP3+1 ;( AL )← 07-01-1=05H , CF=AF=0

AAS AAS ;( AL ) =05H ,未调整未调整 CF=AF=0

MOV DH , AL ;( AL )→(( DHDH ))

所以,(( DXDX )) =0504BCD=0504BCD ,,正是十进制数 54 的非压缩 BCD 格式。

Page 175: 第 3 章   8086 汇编语言程序设计

( 5 )、 AAM ( ASCII adjust for multiply) 乘法 ASCII 调整指令

格式: AAM

执行操作执行操作:( AX ) 把( AL )中的积调整到非压缩的 BCD 码。

条件:条件:参加相乘的两个非压缩参加相乘的两个非压缩 BCDBCD 码(要求高码(要求高 44 位为位为 00 ),),

这条指令必须紧跟在这条指令必须紧跟在 MULMUL 指令之后。结果在指令之后。结果在 ALAL 寄存器寄存器中。中。

调整方法:调整方法:

(( ALAL )) /0AH /0AH (( AHAH )商,)商,

(( ALAL )) /0AH /0AH (( ALAL )余数)余数

条件码设置:

根据( AL )设置条件码 SF 、 ZF 、 PF 。

但 0F 、 CF 、 AF 无定义。

Page 176: 第 3 章   8086 汇编语言程序设计

应用举例:

例 1 : 设( AL ) =07H(BCD) ,( BL ) =09H(BCD)

MOV AL,07H

MOV BL, 09H

MUL BL ; ( AX ) =003FH

AAM AAM ;(AH)=06H,(AL)=03H ,SF=ZF=0,PF=1

Page 177: 第 3 章   8086 汇编语言程序设计

( 6 )、 AAD ( ASCII adjust for division) 除法 ASCII 调整指令

加法、减法、乘法的 ASCII 调整指令是对二个非压缩码运算以后的结果进行调整。

除法 ASCII 调整指令 AAD:

将存放在( AX )中二位非压缩 BCD 的被除数用被除数用 AADAAD 指令将指令将其调整成二进制数存放于其调整成二进制数存放于 (AL)(AL) 中。中。

操作:( AL )( AH ) × 0AH+ ( AL )

( AH ) 0

标志:对 SF 、 ZF 、 PF 设置

对 OF 、 CF 、 AF 无定义

Page 178: 第 3 章   8086 汇编语言程序设计

AAD 指令用法:

将存放在(将存放在( AXAX )中二位非压缩)中二位非压缩 BCDBCD 的被除数用的被除数用 AADAAD 指指令将其调整成二进制数存放于令将其调整成二进制数存放于 (AL)(AL) 中。然后用中。然后用 DIVDIV 指令指令进行除法,所得商还需用进行除法,所得商还需用 AAMAAM 指令进行调整。指令进行调整。

应用举例:

例 1 :编程实现 73/2 =?

设 (AX)=0703H, (BL)=02H

MOV AX, 0703H

MOV BL, 02H

AAD ;(AL)=49H (73D)

DIV BL ;(AL)=24H(商), (AH)=01H(余数)

AAM ; (AH)=03H , (AL)=06H

Page 179: 第 3 章   8086 汇编语言程序设计

四 . 逻辑运算指令

逻辑指令指令分类

逻辑运算 AND、OR、XOR、NOT、TEST

移 位 SHL、SAL、SHR、SAR

循环移位 ROL、ROR、RCL、RCR

Page 180: 第 3 章   8086 汇编语言程序设计

逻辑运算 :与、或、非、异或

特点:二进制数运算 ,按位进行

`与 `运算:有 0 则 0 ,全 1 则

`或 `运算:有 1 则 1 ,全 0 则0

AB

00

01

10

11

A∧ B 0 0 0 1

A B

00

01

10

11

A∨ B 0 1 1 1

例: 1101 1100

∧ 1011 1010

1001 1000

例: 1010 1100

∨ 0011 1001

1011 1101

Page 181: 第 3 章   8086 汇编语言程序设计

` 非 `运算: 0 则 1 , 1则 0

` 异或 `运算:异则 1 ,同则 0

A 0 1

A 1 0

A B

00

01

10

11

A∨ B 0 1 1 0

例: 1011 1010

0100 0101

例: 1010 1100

∨ 0011 1001

1001 0101

Page 182: 第 3 章   8086 汇编语言程序设计

指令格式 执行操作

AND dst,src (dst) ← (dst)∧(src)

OR dst,src (dst) ← (dst)∨(src)

NOT oprd (oprd)← (oprd)

XOR dst,src (dst) ← (dst)∨(src)

TEST oprd1,oprd2 (oprd1)∧(oprd2)

1. 逻辑运算指令

Page 183: 第 3 章   8086 汇编语言程序设计

AND AL , 0000 1111B

OR BX , 00FFH

NOT CL

XOR DL, AL

TEST AL, 0000 0001B

除 NOT 指令单操作数外,其它均为双操作数 可进行字节或字操作 NOT 指令不影响标志

TEST 只影响标志位,不影响操作数。

其他指令置 CF 、 OF 为 0 , AF 不定 ( 无意义 )

SF 、 ZF 、 PF 据结果置位

Page 184: 第 3 章   8086 汇编语言程序设计

例 数字字符的 ASCII → 对应的二进制数

ASCII

数字 0~9 30H~39H

应用: MOV AH, 1 ; 利用 DOS调用 INT 21H ; 从键盘输入字符到 AL中 AND AL, 0000 1111B ;高 4 位为 0 ,低 4 位不变 、、、

0011 1001B 39 H ∧ 0000 1111 B 0F H 0000 1001B 09 H

Page 185: 第 3 章   8086 汇编语言程序设计

逻辑运算常用于使操作数的某位为 0 或 1, 或测试某位为 0 还是1 。

使某位为 1

用该位与 1 相或,不变的位与 0 或。

使某位为 0

用该位与 0 相与,不变的位与 1 与。

使某位求反 用该位与 1 异或,不变的位与 0异或。

测试某位的值 用 TEST 指令,据标志判断

Page 186: 第 3 章   8086 汇编语言程序设计

例 21H 端口管理中断系统,管理 8 个外设的中断

为 0, 允许键盘中断为 1, 禁止

7 6 5 4 3 2 1 01 0 1 0 0 0 1 0

D7 D6 D5 D4 D3 D2 D1 D0

允许键盘中断: IN AL , 21H ;读入 21 端口内容 AND AL , 1111 1101B ;置 D1 = 0, 其他位不变 OUT 21H , AL ; 送出屏蔽字到 21H 端口禁止键盘中断: IN AL , 21H OR AL , 0000 0010B ; 使 D1 为 1 OUT 21H , AL

Page 187: 第 3 章   8086 汇编语言程序设计

例 379H 端口的 D7 存放打印机的状态

为 0, 表示打印机忙为 1, 打印机空闲

7 6 5 4 3 2 1 01 0 1 0 0 0 1 0

D7 D6 D5 D4 D3 D2 D1 D0

用查询方式控制打印机工作: MOV DX, 379H ask: IN AL, DX ; 从 379H 端口读状态 TEST AL, 1000 0000B ;检测 D7 位 JZ ask ; 为 0 ,打印机忙 ,继续查询print: 、、、 ;输出字符打印

Page 188: 第 3 章   8086 汇编语言程序设计

2. 移位指令

SHL oprd, 1CL

SAL oprd, 1CL

SHR oprd, 1CL

SAR oprd, 1CL

0CF

0CF

CF0

CF

执行操作指令格式

Page 189: 第 3 章   8086 汇编语言程序设计

移位规则

▲ 左移: 高位 ← 低位

右移: 高位 → 低位

▲ 移出位进入 CF 标志

▲ 对移位指令,移出 CF 标志后丢失

▲ 逻辑左移、算术左移的结果相同

▲ 逻辑右移,新移入的信息以 0填入

算术右移,保持最高有效位原来的值(符号为不变)

0CF

0CF

SHL

SAL

CF0

CF

SHR

SAR

Page 190: 第 3 章   8086 汇编语言程序设计

例 若( AL ) =96H, CF=0 执行 SHL AL, 1

执行前: (AL)=96H ,CF=0 1 0 0 1 0 1 1 0

执行后: (AL)=2CH ,CF=1 0 0 1 0 1 1 0 0

执行前: (AL)=96H ,CF=0 1 0 0 1 0 1 1 0

执行后: (AL)=E5H ,CF=1 1 1 1 0 0 1 0 1 CF

例 若( AL ) =96H, CF=0, (CL) =2 执行 SAR AL, CL

Page 191: 第 3 章   8086 汇编语言程序设计

3. 循环移位指令

指令格式 执行操作

CF

CF

CF

CF

ROL oprd, 1CL

ROR oprd, 1CL

RCL oprd, 1CL

RCR oprd, 1CL

Page 192: 第 3 章   8086 汇编语言程序设计

移位规则▲ 左移: 高位 ← 低位

右移: 高位 → 低位

▲ 移出位进入 CF 标志

▲ 对循环移位指令,改变各位的位置,信息不丢失

▲ 带进位循环移位, CF 标志参加循环移位

ROLCF

CF

CF

CF

ROR

RCL

RCR

Page 193: 第 3 章   8086 汇编语言程序设计

例 若( AL ) = 96H, CF=0

执行 ROL AL, 1

执行前: 1 0 0 1 0 1 0 CF=0 , (AL)=96h1

执行后: 0 0 1 0 1 0 1 CF=1, (AL)=2Dh1

例 若( AL ) = 96H, CF=0, (CL)=2

执行 RCR AL, CL

1 0 0 1 0 1 0执行前: 1 CF=0 , (AL)=96H

0 1 0 0 1 1 1右移 1 位: 0 CF=0 , (AL)=4BH

0 0 1 0 0 0 1再 右 移 1 位 : 1 CF=1 , (AL)=25H

Page 194: 第 3 章   8086 汇编语言程序设计

注意事项:

SHL AL, 1 SHR AL, CL ROL BX, 1 RCR AL, CL

源操作数为移位的次数 为 1 可在指令中直接给出 大于 1 时,移位次数需由 CL 给出

RCR AX , 5 SHL BL, AL

目的操作数类型决定操作类型SAL BL , CL 字节操作ROL BX , CL 字操作

当移位次数

oprd 可以是 reg/mem

可进行字节或字操作

Page 195: 第 3 章   8086 汇编语言程序设计

SHL AL, 1

ROL BX, 1

对标志位的影响▲移位指令:

①据结果设置 CF 、 SF 、 ZF 、 PF ,对 AF 无定义②OF 只在移位次数为 1 时有效,其他无定义 移位后,最高有效位发生变化,则 OF=1 ,否则为 0

▲对循环移位指令:①据移位结果设置 CF ,对其他标志无影响②OF 标志与移位指令同

0CF

CF

Page 196: 第 3 章   8086 汇编语言程序设计

逻辑移位可用于无符号数乘除 算术移位 、、 带符号数 、、左移一次,相当于乘 2

右移一次,相当于除 2

例 将 AL 中的带符号数乘 10 , 若 (AL)=X

SAL AL , 1 ; (AL)=2X

MOV BL , AL ; (BL)=2X

SAL AL , 1 ; (AL)=4X

SAL AL , 1 ; (AL)=8X

ADD AL , BL ; (AL)=(8X+2X)=10X

Page 197: 第 3 章   8086 汇编语言程序设计

五 . 控制转移指令

在 8086/8088 中,指令的地址固定由 CS 和 IP 两个寄存器决定。

CPU 总线 内存

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB

Page 198: 第 3 章   8086 汇编语言程序设计

CS 和 IP 两寄存器的内容决定了程序的流程

改变 CS 和 IP 寄存器的值, 就改变了程序执行的流程。

BB0001B12090

… … … … … …

指令 1

指令 2

指令 3

指令 n

指令 n+1

指令 n+3

CS:IP

CS:IP

Page 199: 第 3 章   8086 汇编语言程序设计

8086/8088 中 CS 和 IP 的变化规则:

第一条指令在内存的 ROM区。

… … … … … …

… … … … … ……

0000:000h

FFFF:0000h

内存

1 、 RESET复位后, ( CS ) = FFFFH , ( IP ) = 0

故 8088 从内存 FFFF:0000H 处取第一条指令执行。

Page 200: 第 3 章   8086 汇编语言程序设计

2 、非控制转移指令,指令本身对 CS 和 IP 均无操作, 形成顺序执行结构。

BB0001B12090

指令 1

指令 2

指令 3

CS:IP

顺序执行结构: 顺序存放,顺序执行 程序是指令的集合 指令在内存中顺序存放 对非控制转移指令, CPU 取来一条指令后, 自动将 IP 的值加上该指令的字节数, 使 IP顺序指向下一条指令, CPU 取来紧连着的指令执行。

( 此时 IP 的变化由 CPU 内部的硬件自动完成 )

Page 201: 第 3 章   8086 汇编语言程序设计

3 、 控制转移指令以 CS 和 IP 为主要操作对象, 改变 CS 和 IP 的值,使程序产生分支、调用结构。

指令 1

指令 2

指令 3

指令 4

39D87D0287C3A30020

CS:IP 分支结构、调用结构:

顺序存放,非顺序执行

CMP AX, BX JGE great

XCHG AX, BX

great: MOV [max], AX

、、、 控制转移指令 JGE 可以改变 IP 的值 , 使程序非顺序执行

Page 202: 第 3 章   8086 汇编语言程序设计

指令类型 助记符无条件转移 JMP

条件转移

JE/JZ, JNE/JNZ, JS, JNS, JO, JNO

JP, JNP, JC, JNC, JCXZ

JA/JNBE, JAE/JNB, JB/JNAE, JBE/JNA

JG/JNLE, JGE/JNL, JL/JNGE, JLE/JNG

循环控制 LOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ

过程调用 CALL, RET

中断指令 INT, INTO, IRET

控制转移指令分类

掌握: JMP, JZ, JNZ, JC, LOOP

CALL, RET, INT N, IRET

Page 203: 第 3 章   8086 汇编语言程序设计

控制转移指令( JMP 、 Jcc 、 LOOPxx 、 CALL )概述

例 JMP exit

JZ zero

LOOP nxet

CALL display

指令格式: 助记符 操作数

助记符 JMP 、 Jcc 、 LOOPxx 、 CALL

操作数 给出要转移到的目的地址

Page 204: 第 3 章   8086 汇编语言程序设计

目的地址在 reg 、 mem 中,取来指令后间接得到目的地址

操作数 (目的地址 ) 的三种表示方法:

目的地址在指令中,取来指令后直接得到目的地址

例 CMP AX, BX JGE great XCHG AX, BX great: MOV [max], AX

例 JMP AX JMP WORD PTR [ BX ]

①符号地址 ( 标号或过程名 )

②寄存器 reg

③存储器 mem

Page 205: 第 3 章   8086 汇编语言程序设计

◢ 符号地址 : 在汇编格式指令中用符号来表示地址 可以是标号、过程名 ( 子程名 )

标号 指示指令所在的地址。 用 符号名: 表示。

例 CMP AX, BX JGE great XCHG AX, BX great: MOV [max], AX

根据标号与控制转移指令所在位置,标号有三种类型:SHORT 短属性 NEAR 近属性 FAR 远属性

Page 206: 第 3 章   8086 汇编语言程序设计

SHORT 短属性标号标号与控制转移指令在同一段中 ,标号的偏移地址距离控制转移指令的偏移地址( -128 ~ 127 )

XXXX:(yyyy-128) next: 、、、 、、、 、、、 、、、

Jcc next XXXX:yyyy 、、、 、、、 、、、 、、、 XXXX:(yyyy+127) next: 、、、

位移量 = 符号地址的偏移量 - 当前 IP 的值SHORT属性标号的位移量在( 00~FFH ) , 用 1 个字节存放

-128

+127

Page 207: 第 3 章   8086 汇编语言程序设计

NEAR近属性标号标号与控制转移指令在同一段中 ,标号的偏值在 0000 ~ FFFFH 。

XXXX:0000 next: 、、、 、、、 、、、 、、、

JMP next XXXX:yyyy 、、、 、、、 、、、 、、、 XXXX:FFFF next: 、、、 位移量 = 符号地址的偏移量 - 当前 IP 的值 NEAR属性标号的位移量在( 0000~FFFFH ),用 1 个字存放

-yyyy

FFFF-yyyy

Page 208: 第 3 章   8086 汇编语言程序设计

FAR 远属性标号标号与控制转移指令不在同一段中。

AAAA:bbbb next: 、、、 、、、 、、、 、、、

JMP next XXXX:yyyy 、、、 、、、 、、、 、、、 ZZZZ:wwww next: 、、、

用 2 个字分别存放符号地址的段值、偏移值

Page 209: 第 3 章   8086 汇编语言程序设计

• 过程名 ( 子程名 )

过程指示过程 ( 子程 )第一条指令的地址。

例 display PROC near 、、、 、、、 、、、

display ENDP

按过程与调用语句间的位置,过程有两种类型:NEAR 类型:调用指令与过程在同一个段中FAR 类型:调用指令与过程不在同一个段中

过程定义方法:符号名 PROC 类型 、、、

、、、 、、、

符号名 ENDP

Page 210: 第 3 章   8086 汇编语言程序设计

例 NEAR 类型过程 (调用指令与过程在同一个段中 )

code SEGMENT ;code 段 、、、 、、、 CALL sub ; 调用

、、、 、、、 、、、 、、、 sub PROC NEAR ; 过程定义

、、、 、、、 、、、 RET ;返回 sub ENDP

code ENDS

Page 211: 第 3 章   8086 汇编语言程序设计

例 FAR 类型过程 (调用指令与过程不在同一个段中 )

code1 SEGMENT ;code1 段 、、、 、、、 CALL display ;调用 、、、 、、、 code1 ENDS

code2 SEGMENT ;code2 段 、、、 display PROC FAR ; 过程定义 、、、 、、、 、、、 RET ;返回 display ENDP

code2 ENDS

Page 212: 第 3 章   8086 汇编语言程序设计

◢ 当前 IP 的值为控制转移指令下一条指令的偏移地址。◢ 位移量 = 符号地址的偏移量 - 当前 IP 的值。 符号地址(目标地址) = 当前 IP 的值 + 位移量

指令格式: 助记符 操作数

操作数 执行操作符号地址 (SHORT) (IP) ← (IP)+ 8位位移量

符号地址 ( NEAR属性) (IP) ← (IP)+ 16位位移量reg (16位)

mem ( DW类型 )

(IP) ← ( reg )

(IP) ← (mem)

符号地址 ( FAR属性) (IP) ← 符号地址的偏值 (CS) ← 符号地址的段值

mem ( DD类型 ) (IP) ← ( mem )

(CS) ← (mem+2 )

Page 213: 第 3 章   8086 汇编语言程序设计

转移方式 CS 操作数 跳转范围

段内直接短 方 式 不变

符号地址(SHORT)

-128 ~ 127即 0~FFH

段内直接近 方 式

不变 符号地址(NEAR属性)

一个段内0~FFFFH

段 内间接方式 不变

regmem (DW类型)

一个段内0~FFFFH

段 间直接方式

变 符号地址(FAR属性)

整个内存0~FFFFFH

段 间间接方式 变

mem(DD类型)

整个内存0~FFFFFH

转移方式:由 CS 是否变化、以及操作数类型决定

Page 214: 第 3 章   8086 汇编语言程序设计

转移方式无条件转移

JMP

条件转移Jcc

循环转移LOOPxx

子程调用CALL

段内直接短 方 式

√ √ √ ×

段内直接近 方 式

√ × × √

段 内间接方式

√ × × √

段 间直接方式

√ × × √

段 间间接方式

√ × × √

各控制转移指令允许使用的转移方式

Page 215: 第 3 章   8086 汇编语言程序设计

例 JMP again

JMP BX

JMP WORD PTR [BX]

JMP DWORD PTR [BX]

Jnz next

( 若 next 的位移量在 -128~127)

Jz AX

LOOP BX

Jnz next

( 若 next 的位移量超出 -128~127)

指令 JMP 、 Jcc 、 LOOPxx 、 CALL 本身对标志无影响。

×

Page 216: 第 3 章   8086 汇编语言程序设计

(1) 无条件转移指令 JMP

格式     JMP 目标地址  执行操作  无条件转移到目标地址处 转移方式 5 种方式均可

例  、、、 、、、 JMP next 、、、 、、、next : MOV AX , BX 、、、

Page 217: 第 3 章   8086 汇编语言程序设计

(2) 条件转移指令

格式  Jcc 符号地址

测试条件的助记符

执行 当转移条件满足,转向目标地址去执行。 当 、、 不满足,执行 Jcc 后的下一条指令。

转移方式 只允许段内直接短方式,跳转范围在 -128~127

  例  、、、

CMP AX, BX JZ   zero ; ZF =1 ? 、、、 、、、 zero : MOV   flag,   0 、、、

Page 218: 第 3 章   8086 汇编语言程序设计

按转移条件不同,条件转移指令可以分为四大类:① 以单个状态标志作为转移条件

② 以 CX 的值为 0 作为转移条件

助记符 转移条件JZ ZF=1

JS SF=1

JO OF=1

JP PF=1

JC CF=1

助记符 转移条件JNZ ZF=0

JNS SF=0

JNO OF=0

JNP PF=0

JNC CF=0

助记符 转移条件JCXZ CX=0

Page 219: 第 3 章   8086 汇编语言程序设计

③ 以两个无符号数比较的结果作为转移条件

④ 以两个带符号数比较的结果作为转移条件

助记符 转移条件

JA/JNBE CF∨ ZF=0 高于/不低于等于

JAE/JNB/JNC CF=0 高于等于/不低于/无进位

JB/JNAE/JC CF=1 低于/不高于等于/有进位

JBE/JNA CF∨ ZF=1 低于等于/不高于

助记符 转移条件

JG/JNLE (SF⊕ OF)∨ ZF=0 大于/不小于等于

JGE/JL SF⊕ OF=0 大于等于/不小于

JL/JNGE SF⊕ OF=1 小于/不大于等于

JLE/JNG (SF⊕ OF)∨ ZF=1 小于等于/不大于

Page 220: 第 3 章   8086 汇编语言程序设计

补充 : 调用 DOS 功能在屏幕上显示单字符方法

在屏幕上显示字符“ 1” :

MOV DL, 31H ; 将字符的 ASCII码放在 DL 中

MOV AH, 2H ; 功能号 2 放在 AH 中

INT 21H ;DOS 中断程序调用

Page 221: 第 3 章   8086 汇编语言程序设计

例 将 BL 寄存器的内容按二进制形式显示出来

1 0 1 0 0 1 1 0(BL)

MOV CX , 8 ; 显示字符个数为 8next: SHL BL , 1 ; 将显示位移至 CF 中

JC one ;CF=1? MOV DL , 30H ;CF=0, 将 0 的 ASCII 放在 DL 中 JMP exit

one: MOV DL , 31H ;CF=1, 将 1 的 ASCII 放在 DL 中exit: MOV AH , 2

INT 21H ;调用 DOS 功能显示 DEC CX ;循环次数减 1 JNZ next ; 判断是否结束 、、、

31 30 31 30 30 31 31 30

MOV DL, BL MOV AH, 2HINT 21H

思考 : 1. 去掉指令 JMP exit ,程序执行结果会怎样? 2. 将指令 SHL 改为 SHR ,程序执行的结果会怎样?

Page 222: 第 3 章   8086 汇编语言程序设计

1 0 1 0 0 1 1 0

0 1 0 0 1 1 0 1

0 0 0 0 0 0 0 1

0 0 1 1 0 0 0 1

编程方法 2:1 0 1 0 0 1 1 0(BL)

MOV CX , 8 ; 显示位数为 8

next: ROL BL , 1 ; 将显示位移至 D0位

MOV DL , BL ; 放在 DL 中 AND DL , 01H ; 只保存显示位的值 ADD DL , 30H ; 转换成相应的 ASCII

MOV AH , 2

INT 21H ;调用 DOS 功能显示 DEC CX ;循环次数减 1

JNZ next ; 判断是否结束 、、、

31 30 31 30 30 31 31 30

Page 223: 第 3 章   8086 汇编语言程序设计

( 3) 循环指令

格式  LOOPxx  符号地址

执行 ①( CX ) ← ( CX ) - 1 此操作不影响标志

② 检查转移条件,满足,转向目标地址去执行 ;

    不满足,执行 LOOPxx 后一条指令

转移方式 只允许段内直接短方式,跳转范围 -128~127

助记符 转移条件 不转移条件LOOP CX≠0 CX=0

LOOPZ CX≠0且 ZF=1 CX=0或 ZF=0

LOOPNZ CX≠ 0且 ZF=0 CX=0或 ZF=1

与条件转移指令不同的是,循环指令隐含 ( CX ) 减 1 操作。

Page 224: 第 3 章   8086 汇编语言程序设计

用循环指令改写上例 :

将 BL 寄存器的内容按二进制形式显示出来

MOV CX , 8

next: ROL BL , 1

MOV DL , BL

AND DL , 0000 0001B

ADD DL , 0011 0000B

MOV AH , 2

INT 21H

DEC CX

JNZ next 、、、

LOOP next

Page 225: 第 3 章   8086 汇编语言程序设计

循环指令说明:

比较两串时,当有字符不等,就可退出,说明两字符串不等。     可用 LOOPZ ,当相等时继续比较。

在串中查找字符,查到了,就可退出,     可用 LOOPNZ ,不相等时继续查找。

LOOPZ 和 LOOPNZ提供了提前结束循环的可能 ,

不一定要等到 (CX)= 0才退出循环。

LOOP退出循环条件是( CX ) = 0

执行完 LOOPNZ 或 LOOPZ 后,根据 ZF 标志的值判断结果

对查找字符, ZF=1, 说明找到;否则没有找到。 对串比较, ZF=1, 说明两串相等;否则不等。

Page 226: 第 3 章   8086 汇编语言程序设计

例 在 string 字符串中查找空格字符,串长度为 N 。

‘A’ ‘B’ ‘C’ ‘D’ ‘ ’ ‘E’ 、、、 ‘Y’ ‘Z’

1234:0000 string

DS:BX

修改偏址 BX

Y

N

AL ← 关键字

CX ← 串长度

DS : BX ← 串首址

[BX] 是关键字?

(CX) ← (CX)-1

找到处理未找到处理

(CX) = 0 ?Y

N

结束出口

Page 227: 第 3 章   8086 汇编语言程序设计

用条件转移: MOV CX , N

MOV AX, SEG string MOV DS, AX LEA BX , string MOV AL , 20H

next : CMP AL , [BX] JZ find INC BX DEC CX JNZ next 未找到处理 JMP exit

find : 找到处理exit : 结束出口

在 string 字符串中查找空格字符,串长度为 N 。

修改偏址 BX

Y

N

AL ← 关键字

CX ← 串长度

DS : BX ← 串首址

[BX] 是关键字?

(CX) ← (CX)-1

找到处理未找到处理

(CX) = 0 ?Y

N

结束出口

Page 228: 第 3 章   8086 汇编语言程序设计

用循环指令: MOV CX , N MOV AX, SEG string MOV DS, AX LEA BX , string MOV AL , 20H

next : CMP AL , [BX] PUSHF INC BX POPF LOOPNZ next JZ find 未找到处理 JMP exit

find : 找到处理exit : 结束出口

修改偏址 BX

Y

N

AL ← 关键字

CX ← 串长度

DS : BX ← 串首址

[BX] 是关键字?

(CX) ← (CX)-1

找到处理未找到处理

(CX) = 0 ?Y

N

结束出口

Page 229: 第 3 章   8086 汇编语言程序设计

思考 : ① 去掉指令 JMP exit ,程序执行结果会怎样? ② PUSHF 、 POPF 可否去掉?若要去掉,程序如何修改? ③ 执行完 LOOPNZ 后,可否根据 CX=0 来判断查找结果? 有人认为 CX=0 ,即说明没找到,对吗?

用条件转移: MOV CX , N

MOV AX, SEG string MOV DS, AX LEA BX , string MOV AL , 20H

next : CMP AL , [BX] JZ find INC BX DEC CX JNZ next 未找到处理 JMP exit

find : 找到处理 exit : 结束出口

用循环指令: MOV CX , N MOV AX, SEG string MOV DS, AX LEA BX , string MOV AL , 20H

next : CMP AL , [BX] PUSHF INC BX POPF LOOPNZ next JZ find 未找到处理 JMP exit

find : 找到处理exit : 结束出口

Page 230: 第 3 章   8086 汇编语言程序设计

DEC BXnext : INC BX CMP AL, [BX]

MOV CX , N MOV AX , SEG string MOV DS , AX LEA BX , string MOV AL , 20H

next : CMP AL , [BX] PUSHF

INC BX POPF LOOPNZ next JZ find 未找到处理

、、、 JMP exitfind : 找到处理

、、、

去掉 PUSHF 、 POPF 指令,程序改写为:

Page 231: 第 3 章   8086 汇编语言程序设计

( 4) 调用和返回指令

子程序

调用

返回

返回指令

、、、

、、、

、、、

、、、

调用指令

、、、

、、、

、、、

、、、

主程序

子程序

、、、

Page 232: 第 3 章   8086 汇编语言程序设计

指令类型 助记符

过程调用和返回调用指令 CALL

返回指令 RET

中断调用和返回

中断调用 INT

中断返回 IRET

溢出中断 INTO

Page 233: 第 3 章   8086 汇编语言程序设计

调用指令 CALL

① 段内直接调用

格式 CALL 符号地址 ;NEAR属性

执行 ( SP ) ← ( SP ) - 2

( SS : SP ) ← ( IP )

( IP ) ← 符号地址的偏址 ; 转至符号地址处取指令

入栈保存返回地址偏值

Page 234: 第 3 章   8086 汇编语言程序设计

② 段间直接调用

格式 CALL 符号地址 ; FAR属性执行

( SP ) ← ( SP ) - 2

( SS : SP ) ← ( CS )

( SP ) ← ( SP ) - 2

( SS : SP ) ← ( IP )

( IP ) ← 符号地址的偏址

( CS ) ← 符号地址的段址

入栈保存返回地址段值

入栈保存返回地址偏值

转至符号地址

Page 235: 第 3 章   8086 汇编语言程序设计

返回指令 RET

② 段间返回格式 RET 或 RETF

执行 ( IP ) ← ( SS : SP ) ( SP ) ←( SP )+ 2

( CS ) ← ( SS :SP ) ( SP ) ← ( SP ) + 2

从堆栈取返回地址偏值

从堆栈取返回地址偏值

从堆栈取返回地址段值

① 段内返回 格式 RET

执行 ( IP ) ← ( SS : SP )

( SP ) ← ( SP ) + 2

Page 236: 第 3 章   8086 汇编语言程序设计

段内和段间返回指令的汇编语言格式均可用 RET , 但机器码不同,段内为 C3H, 段间为 CBH, 汇编程序据过程类型确定返回类型。

例 1 display PROC NEAR 、、

、、 C3H 、、 RET ;NEAR 属性的过程对应段内返回 display ENDP

例 2 display PROC FAR 、、

、、 CBH 、、 RET ;FAR属性的过程对应段间返回 display ENDP

Page 237: 第 3 章   8086 汇编语言程序设计

例 段内直接调用 code SEGMENT 、、、 、、、 CALL sub

2000 : 200H → 、、、 、、、 、、、 、、、 sub PROC NEAR

2000 : 300H → 、、、 、、、 、、、 RET sub ENDP

code ENDS

0002A450

1000:1004SS:SP

调用后 (IP)=300H

1000:1006SS:SP

返回后 (IP)=200H

0002A4501000:1006SS:SP

1000:1004SS:SP

Page 238: 第 3 章   8086 汇编语言程序设计

例 段间直接调用 code1 SEGMENT 、、、 、、、 CALL sub

2000 : 100H→ 、、、 、、、 code1 ENDS

code2 SEGMENT 、、、 sub PROC FAR

3000 : 200H→ 、、、

、、、 、、、 RET sub ENDP code2 ENDS

1000:1002SS:SP

调用后 (IP)=200H (CS)=3000H

1000:1006SS:SP

00010020A450

返回后 (IP)=100H, (CS)=2000H

1000:1002SS:SP

1000:1006SS:SP

00010020A450

Page 239: 第 3 章   8086 汇编语言程序设计

注意: 在调用、返回指令中, 利用堆栈保存、恢复返回地址。

对堆栈的操作应有目的性, 不乱用堆栈操作,不随意修改堆栈内容, 否则易造成死机。

Page 240: 第 3 章   8086 汇编语言程序设计

例 段内直接调用 code SEGMENT 、、、 、、、 CALL sub

2000 : 200H → 、、、 、、、 、、、 、、、 sub PROC NEAR

2000 : 300H → 、、、 MOV AX, 1234h PUSH AX 、、、 RET sub ENDP

code ENDS

0002A450

1000:1004SS:SP

调用后 (IP)=300H

1000:1006SS:SP

返回后 (IP)=1234h

1000:1002SS:SP

1000:1006SS:SP

34120020A450

结论:不能正常返回 300h调用处继续执行

Page 241: 第 3 章   8086 汇编语言程序设计

( 5) 中断调用、中断返回指令

▲中断子程以类型号 N 来区分

共有 256 个类型号( 0~FFH, 即 0~255 )

类型号 0 处理除 0 错误的中断子程

类型号 9H 处理键盘操作的中断子程

类型号 21H 与 DOS 系统功能相关的中断子程

▲中断子程:

是一种特殊的子程序, (DOS 系统中有大量这样的子程,用户也可以编写这样的子程)

特殊在它的调用方法与普通的子程序不同。

Page 242: 第 3 章   8086 汇编语言程序设计

▲中断向量:指中断子程的入口地址 , 包括段地址、偏移地址

偏移地址段地址

0:N×4

0:N×4+ 2

中断子程 N 的入口地址在内存中的位置

其中:前两个单元存放偏移地址

后两个单元 存放段地址

类型 N 的中断向量固定存放在 4 个内存单元中,即:

( 0 : N×4 ~ 0 : N×4 + 3 )

Page 243: 第 3 章   8086 汇编语言程序设计

中断子程 1 的入口地址:

段地址: 0070h

偏移地址: 0465h

65h04h70h00h

0:0004

0:0006

例:已知内存 0:4~7 单元的内容如图,

问中断类型号为 1 的中断子程的入口地址是多少?

D:\> DEBUG-D 0:0 L200000:0000 9E 0F C9 00 65 04 70 00-16 00 13 08 65 04 70 000000:0010 65 04 70 00 54 FF 00 F0-58 7F 00 F0 F5 E7 00 F0-思考:用什么命令可以查看到该中断子程? - U 0070:0465

Page 244: 第 3 章   8086 汇编语言程序设计

▲中断向量表:指存放 256 个中断向量的内存区域

4 × 256 = 1024 = 1K

中断向量表地址为 0 : 0 ~ 0 : 03FF H

即 0 段前 1K 个内存单元,低端 1K 内存。

Page 245: 第 3 章   8086 汇编语言程序设计

类型 FF 中断向量

类型 0 中断向量 、、 段值类型 0向量的偏值

类型 1向量的偏值 、、 段值

1020H3040H

类型 FF向量的偏值 、、 段值

类型 1 中断向量

类型 N 中断向量

0 : 0000

0 : 0004

0 : N×4

0 : 03fc

中断向量表

0:0~3FF

例中类型 N 的中断子程从 3040:1020H开始

Page 246: 第 3 章   8086 汇编语言程序设计

▲ 有的中断子程在软、硬件条件满足时, CPU会自动去执行 (在第六章 中断技术中 介绍)

例如:

① 除 0 时, CPU 自动执行类型 0 的中断子程

② 按下某键, CPU 自动执行类型 9 的中断子程

Page 247: 第 3 章   8086 汇编语言程序设计

例 段内直接调用 code SEGMENT 、、、 、、、 CALL sub

2000 : 200H → 、、、 、、、 、、、 、、、 sub PROC NEAR

2000 : 300H → 、、、 MOV AX, 1234h PUSH AX 、、、 RET sub ENDP

code ENDS

0002A450

1000:1004SS:SP

调用后 (IP)=300H

1000:1006SS:SP

返回后 (IP)=1234h

1000:1002SS:SP

1000:1006SS:SP

34120020A450

结论:不能正常返回调用处继续执行

Page 248: 第 3 章   8086 汇编语言程序设计

中断调用指令 INT

保存现场

取中断子程入口地址

入栈保存 IP

入栈保存 CS

入栈保存 PSW

清 IF 标志清 TF 标志

格式 INT N ; 其中 N=0 ~FFH 即 0~255

执行 ( SP ) ← ( SP ) - 2 ( SS : SP )← ( PSW )

IF ← 0 TF ← 0

( SP ) ← ( SP ) - 2 ( SS : SP )← ( CS )

( SP ) ← ( SP ) - 2 ( SS : SP )← ( IP )

( IP ) ← ( 0: N× 4 ) ( CS ) ←( 0: N×4 + 2 )

Page 249: 第 3 章   8086 汇编语言程序设计

执行 INT 前 SS : SP

(PSW)

(CS)

(IP) SS : SPIF=0 , TF=0

从中断向量表获取中断子程的入口地址,CS:IP 转至中断子程入口取指令

INT 指令

Page 250: 第 3 章   8086 汇编语言程序设计

中断返回指令 IRET

格式 IRET

执行 ( IP ) ← ( SS : SP )

( SP ) ← ( SP ) + 2

( CS ) ← ( SS : SP ) ( SP ) ← ( SP ) + 2

( PSW ) ← ( SS : SP ) ( SP ) ← ( SP ) + 2

从堆栈取返回地址,并恢复现场

Page 251: 第 3 章   8086 汇编语言程序设计

CS:IP 转至主程被中断处取指令

执行 IRET 后 SS : SP

(PSW)

(CS)

(IP)执行 IRET 前 SS : SP

、、、、、、、、、、、、、、、、、、、、、

Page 252: 第 3 章   8086 汇编语言程序设计

内 存 0000 : 0000 → 、、 、、0:1C×4 =70h → FF53H 中断向量表0:1C×4+2=72h→ F000H (1K 字节 ) 、、 0 : 03FFH → 、、 、、 、、 INT 1CH 中断调用 1271:0102H → 、、 、、 、、 、、 、、 F000:FF53H → 、、 、、 中断子程 、、 IRET 中断返回 、、 、、 F000:FFFFH → 、、

(PSW)=0300HIF=1,TF=1

2000:0106SS:SP

INT 1C 执行前

IF=1 , TF=1 (PSW) =0300H

(CS) )=1271H

2000:0100SS:SP

12

71

00

03

01

02

INT 1C 执行后

(IP) =0102H (PSW)=0000HIF=0 , TF=0

IRET 执行后

2000:0106SS:SP

(CS)=F000, (IP)=FF53

、、、、

了解 INT 指令调用中断子程 IRET 指令中断返回过程

Page 253: 第 3 章   8086 汇编语言程序设计

D:\TEACH\DEBUG

-A ; 汇编一条中断指令 2F68:0100 INT 1C

2F68:0102

-R ;查看执行指令前各寄存器内容 AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000

DS=0F68 ES=0F68 SS=0F68 CS=2F68 IP=2100 NV UP EI PL NZ NA PO NC

0F68:0100 CD1C INT 1C

-T ;T 单步执行 INT 1C

AX=0000 BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000

DS=0F68 ES=0F68 SS=0F68 CS=F000 IP=FF53 NV UP DI PL NZ NA PO NC

F000:FF53 CF IRET

-D SS:FFE8 L08 ;查看执行完后堆栈内容 0F68:FFE0 02 01 68 2F 02 F2 00 00 . . h.....

-D 0:70 L10 ;查看中断向量表 0:70 – 0:73

0000:0070 53 FF 00 F0 A4 F0 00 F0-22 05 00 00 35 58 00 C0 ........"...5X..

-U F000:FF53 ;查看 1C 类型的中断子程 F000:FF53 CF IRET . . .

利用 DEBUG 学习 INT 指令 :

Page 254: 第 3 章   8086 汇编语言程序设计

注意:

▲ 不随意修改中断向量表的内容,否则易造成死机

▲ 不随意修改堆栈内容

Page 255: 第 3 章   8086 汇编语言程序设计

溢出中断调用 INTO

格式 INTO

执行 OF 为 1 时,执行 INT 4; OF 为 0 时,执行 INTO 下一条执行。

例 、、、 INTO 、、、 、、、 、、、 、、、

类型 4中断子程 → 、、、 、、、 、、、

Page 256: 第 3 章   8086 汇编语言程序设计

.陆 处理机控制指令1 、标志处理指令

CLC, STC, CMC, CLD, STD, CLI, STI

2 、 处理机控制指令

HLT, NOP, WAIT, ESC, LOCK

Page 257: 第 3 章   8086 汇编语言程序设计

1 、 标志处理指令

▲设置和清除标志的指令,只影响指令指定的标志

指令格式 执行操作CLC CF=0

STC CF=1

CLM CF ← CF

CLD DF=0

STD DF=1

CLI IF=0

STI IF=1

Page 258: 第 3 章   8086 汇编语言程序设计

2 、 处理机控制指令

① 暂停指令 HLT

格式 HLT

执行 使 CPU 处于暂停状态

用于等待外部中断,中断处理结束后,继续执行 HLT 后的下一条指令

例 、、、 、、、

STI ; 允许外部中断 HLT ;等待中断 MOV AX, 0

、、、 、、、(HLT 指令在第 6章中断技术用到 )

Page 259: 第 3 章   8086 汇编语言程序设计

② 空操作指令 NOP

格式 NOP

指令不执行任何操作

mov BX, [100] 00B8

01

07

3Acmp AL,[BX]

B8FE11

mov BX, [100] 00B8

01

90

90

cmp AL,[BX]

90

3A07

nopnopnop

mov CX, 20HB9 20 00

例:

(也可用 NOP 指令进行短延时 ( 教材中的一些例子用到)

其机器码占一个字节单元, 在调试程序时,修改程序用。

Page 260: 第 3 章   8086 汇编语言程序设计

七、串处理指令

串的基本概念 顺序存放在内存中的一组数据,称为串。 用串的首(末)地址、元素类型、串的长度表示。

1234:0000string

DS:BX

‘A’ ‘B’ ‘C’ ‘D’ ‘ ’ ‘E’ 、、、 ‘Y’ ‘Z’

112233

1a2b3c4d

Page 261: 第 3 章   8086 汇编语言程序设计

串操作种类

①串传送 将串从内存某一区域传送到另一区域。 ② 从串取 从串中取出某一元素。 ③ 存入串 将某个数据存入串中。 ④ 串比较 对两个串进行比较。 ⑤ 搜索串 在串中搜索(查找)某数据(关键字)

Page 262: 第 3 章   8086 汇编语言程序设计

串处理指令格式

重复控制前缀   串指令

控制重复次数  基本操作

MOVSB 、 MOVSW 串传送REP LODSB 、 LODSW 从串取REPZ STOSB 、 STOSW 存入串REPNZ CMPSB 、 CMPSW 串比较 SCASB 、 SCASW 搜索串

例 REP MOVSB REPZ CMPSB REPNZ SCASW

Page 263: 第 3 章   8086 汇编语言程序设计

① 串指令

串传送 MOVS

从串取 LODS

存入串 STOS

串比较 CMPS

搜索串 SCAS

Page 264: 第 3 章   8086 汇编语言程序设计

▲串指令的特点

① 指令给出串操作的种类、类型,而操作数隐含给出。 如 MOVSB ; 字节 MOVSW ; 字

② 源串 由 DS : SI 指向的单元 目的串 由 ES : DI 指向的单元

③ 指令执行后,指针据 DF 标志、操作类型自动修改 字节操作 1 ; 字操作 2

DF= 0 用 + ; DF= 1 用 -

Page 265: 第 3 章   8086 汇编语言程序设计

④ 只有一个存储器操作数的串指令 如 LODS (从串取) STOS (存入串) SCAS (搜索串)

另一个操作数在 AL ( 字节操作 ) 或 AX ( 字操作 )

⑤影响标志情况 CMPS( 串比较 ) 、 SCAS( 串搜索 ) 影响标志, MOVS( 串传送 ) 、 LODS( 从串取 ) 、 STOS( 存入串 ) 不影响标志。

Page 266: 第 3 章   8086 汇编语言程序设计

串传送

◢ ◢ 格式 MOVSB 字节传送 MOVSW 字传送

◢◢ MOVSB 执行操作 (ES:DI ) ← (DS:SI )   字节传送 (SI ) ← (SI ) 1 修改源串指针

(DI) ← (DI ) 1 修改目的串指针 其中:  DF = 0 ,用 + DF = 1 ,用 -

◢◢ MOVSW 执行操作 (ES:DI ) ← (DS:SI )   字传送 (SI ) ← (SI ) 2 修改源串指针

(DI ) ← (DI ) 2 修改目的串指针其中:  DF = 0 ,用 + DF = 1 ,用 -

Page 267: 第 3 章   8086 汇编语言程序设计

从串取◢ ◢ 格式 LODSB 取字节 LODSW 取字

◢◢ LODSB 执行操作 (AL) ← (DS:SI )   从源串取入 AL

(SI ) ← (SI ) 1 修改源串指针其中:  DF = 0 ,用 + DF = 1 ,用 -

◢◢ LODSW 执行操作 (AX ) ← (DS:SI )   从源串取入 AX

(SI ) ← (SI ) 2 修改源串指针其中:  DF = 0 ,用 + DF = 1 ,用 -

Page 268: 第 3 章   8086 汇编语言程序设计

存入串

◢ ◢ 格式 STOSB 存入字节 STOSW 存入字

◢◢ STOSB 执行操作 (ES:DI) ← (AL)  将 AL 存入目的串 (DI ) ← (DI ) 1 修改目的串指针其中:  DF = 0 ,用 + DF = 1 ,用 -

◢◢ STOSW 执行操作 (ES:DI) ← (AX)  将 AX 存入目的串 (DI) ← (DI ) 2 修改目的串指针其中:  DF = 0 ,用 + DF = 1 ,用 -

Page 269: 第 3 章   8086 汇编语言程序设计

串比较◢ ◢格式 CMPSB 字节比较 CMPSW 字比较

◢◢ CMPSB 执行操作 (DS:SI ) - (ES:DI )   字节比较

(SI ) ← (SI ) 1 修改源串指针 (DI ) ← (DI ) 1 修改目的串指针

◢◢ CMPSW 执行操作 (DS:SI ) - (ES:DI )   字比较

(SI ) ← (SI ) 2 修改源串指针 (DI ) ← (DI ) 2 修改目的串指针

注意: 1. 源串 - 目的串 2. 两数相减,只影响标志,不影响操作数

Page 270: 第 3 章   8086 汇编语言程序设计

搜索串

◢ ◢格式 SCASB 取字节 SCASW 取字

◢◢ SCASB 执行操作 (AL) - (ES:DI )   从目的串搜索字节

(DI ) ← (DI ) 1 修改目的串指针

◢◢ SCASW 执行操作 (AX ) - (ES:DI )   从目的串搜索字节

(DI) ← (DI ) 2 修改目的串指针

两数相减,只影响标志,不影响操作数。

Page 271: 第 3 章   8086 汇编语言程序设计

② 重复控制前缀

重复前缀 REP

当相等重复前缀 REPZ /REPE

当不相等重复前缀 REPNZ /REPNE

Page 272: 第 3 章   8086 汇编语言程序设计

重复前缀 REP

执行过程:(1)当 (CX)= 0 ,结束 REP , 执行 REP 下一条指令。(2)当 (CX)≠0 ,将 CX 的 内容减1 , 执行 REP 后的串指令,返回 (1) 。

例 LEA DI, destination LEA SI, source MOV CX , 20 REP MOVSB MOV AX, 0

只在 (CX)=0 时退出循环

REP执行流程

(CX)=(CX)-1

REP后的串 指 令

Y

NCX=0 ?

Page 273: 第 3 章   8086 汇编语言程序设计

当相等重复前缀 REPZ

执行过程:(1) 当 (CX)= 0 , 结束 REPZ , 执行 REPZ 下一条指令;(2) 当 (CX)≠0 ,将 CX 的内容减 1 , 执行 REPZ 后的串指令;(3) 当 ZF = 1, 返回 (1) ;(4) 当 ZF≠1, 则结束 REPZ,

执行 REPZ 下一条指令。

(CX) 减 1 操作不影响标志 ZF 标志由串操作决定 REPZ执行流程

(CX)=(CX)-1

REPZ后的串 指 令

Y

N

Y

N

CX=0?

ZF=1 ?

Page 274: 第 3 章   8086 汇编语言程序设计

当不相等重复前缀 REPNZ

执行过程:(1) 当 (CX )= 0 , 结束 REPNZ , 执行 REPNZ 下一条指令。(2)当 (CX)≠0 ,将 CX 的内容减 1 , 执行 REPNZ 后的串指令。(3) 当 ZF = 0, 返回 (1);(4) 当 ZF≠0, 则结束 REPNZ,

执行 REPNZ 下一条指令。

REPNZ执行流程

(CX)=(CX)-1

REPNZ后的串 指 令

Y

N

Y

N

CX=0 ?

ZF=0 ?

Page 275: 第 3 章   8086 汇编语言程序设计

例 1 用 REP MOVS 进行数据块传送。 编程:①设置传送方向 用 CLD 使 DF = 0, 地址增加方向(正向) 用 STD 使 DF = 1, 地址减小方向(反向)②设置源串地址 将源串首地址 (DF=0) ,或末地址( DF=1 )放入 DS 、 SI 中。③设置目的串地址 将目的串首地址 (DF=0) ,或末地址( DF=1 )放入 ES 、 DI中。④设置串长度 将串的长度(传送次数)放入 CX 中。⑤字节传送用 REP MOVSB 字传送 用 REP MOVSW

Page 276: 第 3 章   8086 汇编语言程序设计

例 1 编程将存放在 str1 中的 4 字节字符串传送到 str2 定义的缓冲区中。

‘D’‘C’‘B’‘A’str1

str2

Page 277: 第 3 章   8086 汇编语言程序设计

data1 SEGMENT str1 DB ‘ABCD’ ; 源串data1 ENDSdata2 SEGMENT str2 DB 4 DUP(?) ;缓冲区data2 ENDScode SEGMENT 、、、、、、

CLD ;DF=0,正方向传送 MOV AX , data1 ; 源串首地址的段值→ DS MOV DS , AX LEA SI , str1 ; 源串首地址的偏值→ SI MOV AX , data2 ;目的串首地址的段值→ ES

MOV ES , AX LEA DI , str2 ;目的串首地址的偏值→ DI

MOV CX, 4 ; 串长度 CX REP MOVSB ; 串传送

、、、、、、code ENDS

Page 278: 第 3 章   8086 汇编语言程序设计

‘D’‘C’

‘B’‘A’

00H00H00H00H

FC、、、、F3

1234:0000str1

1235:0000str2

A4

1236:0000

程 序

CLD

REPMOVS

BB

data1 SEGMENTstr1 DB ‘ABCD’data1 ENDS

data2 SEGMENTstr2 DB 4 DUP(?)data2 EMDS

code SEGMENT 、、、、、、 CLD MOV AX , data1 MOV DS , AX LEA SI , str1 MOV AX , data2 MOV ES , AX LEA DI , str2 MOV CX, 4 REP MOVSB 、、、、、、

code ENDS

假设程序经汇编、连接后,装入内存的情况如下:

Page 279: 第 3 章   8086 汇编语言程序设计

‘D’‘C’

‘B’‘A’

00H00H00H00H

1234:0000DS:SI

1235:0000ES:DI

(CX)=4

执行 REP前各寄存器的设置

执行一次 MOVSB后

‘D’‘C’

‘B’‘A’

‘A’00H00H00H

1234:0001DS:SI

1235:0001ES:DI

(CX)=3

执行完 REP后

‘D’‘C’

‘B’‘A’

‘A’‘B’‘C’‘D’

1234:0004DS:SI

1235:0004ES:DI

(CX)=0

程序执行结果:

Page 280: 第 3 章   8086 汇编语言程序设计

例 2 比较 string1 和 string2 的两串 , 长度为 8 字节

string1 112233

、、、

、、、1a2b3c

4d

string2112233

、、、

、、、

1a1122

34

Page 281: 第 3 章   8086 汇编语言程序设计

用 REPZ CMPS 进行串比较

编程:① 设置比较方向 (STD 或 CLD)

② 设置源串、目的串地址 将源串首地址 (DF=0 时 ) ,或末地址( DF=1 时)放入 DS 、 SI

将目的串首地址 (DF=0 时 ) ,或末地址( DF=1 时)放入ES 、 DI

③ 设置串长度 将串的长度放入 CX 中④ 按字节比较用 REPZ CMPSB

按字比较 用 REPZ CMPSW

Page 282: 第 3 章   8086 汇编语言程序设计

执行完 REPZ CMPS 后,根据 ZF 判断两串比较结果。

▲ 若 ZF=1, 两串相等,此时: CX=0, 表明串中所有元素已比较完毕 SI 、 DI 指向串尾的下一单元。

▲ 若 ZF=0, 两串不等,此时: CX 的值为剩下的未比较的元素个数。 SI 、 DI 指向不相等元素的下一元素。

Page 283: 第 3 章   8086 汇编语言程序设计

code SEGMENT 、、、、、、 CLD ;DF=0,正向比较 MOV AX , SEG string1 ; 源串首地址→ DS:SI MOV DS , AX LEA SI , string1 MOV AX , SEG string2 ;目的串首地址→ ES:DI MOV ES , AX LEA DI , string2 MOV CX, 8 ; 串长度→ CX REPZ CMPSB ; 串比较 JZ equal ; 利用 ZF 判断比较结果 不相等处理 JMP exit

equal: 相等处理 exit: 、、、code ENDS

Page 284: 第 3 章   8086 汇编语言程序设计

code SEGMENT 、、、、、、 CLD ;DF=0,正向比较 MOV AX , SEG string1 ; 源串首地址→ DS:SI MOV DS , AX LEA SI , string1 MOV AX , SEG string2 ;目的串首地址→ ES:DI MOV ES , AX LEA DI , string2 MOV CX, 8 ; 串长度→ CX REPZ CMPSB

JZ equal 不相等处理 JMP exit equal: 相等处理 exit: 、、、code ENDS

JNZ notequ 相等处理 JMP exit notequ: 不相等处理exit: 、、、

Page 285: 第 3 章   8086 汇编语言程序设计

、、、 、、、112233

44

1a2b3c

4d

11223344

1a2b3c

4d

string1 string2

DS:SI ES:DI (CX)=0, ZF=1

执行完 REPZ CMPSB 后,此时:ZF=1, 两串相等CX=0 , 两串所有元素已比较完SI 、 DI 串尾的下一单元

Page 286: 第 3 章   8086 汇编语言程序设计

、、、 、、、112233

44

1a

4d

11223344

2c

4d

2b3c

3b3c

string1 string2

DS:SI ES:DI (CX)=3,ZF=0

执行完 REPZ CMPSB 后,此时:ZF=0, 两串不等CX=3, 剩下的未比较的元素个数SI 、 DI 指向不相等元素的下一元素。

Page 287: 第 3 章   8086 汇编语言程序设计

例 3 用 REPNZ SCAS 在串中找关键字。

编程步骤:①设置查找方向②设置串地址 将串的首地址 (DF=0 时 ) ,或末地址( DF=1 时)放入 ES 、DI 中。③设置关键字 将关键字放入 AL ( 关键字为字节 ) 或 放入 AX( 关键字为字 ) 。④设置串长度 将串的长度放入 CX 中。⑤查找字节用 REPNZ SCASB

查找字 用 REPNZ SCASW

Page 288: 第 3 章   8086 汇编语言程序设计

执行完 REPNZ SCAS 后,根据 ZF 判断查找结果。

▲ 若 ZF=1, 则串中有关键字,此时: CX 的值为剩下的未搜索的元素个数, DI 指向关键字元素的下一元素, 而关键字在 ( DI )-1 的位置

▲ 若 ZF=0, 则串中无关键字,此时: CX=0 ,表明串中所有元素以搜索完毕 DI 指向串尾的下一单元。

Page 289: 第 3 章   8086 汇编语言程序设计

例 MOV AL, ’$’

、、、 REPNZ SCASB JZ found 未找到处理 JMP exitfound: 找到处理exit: 、、、

关键字元素( DI ) = 0003‘C’

‘$’

‘B’

‘A’

‘D’ ( CX) = 0002 ZF=1

执行后

( DI ) = 0000

(CX) = 0005

(AL) = ‘$’

执行前

注意:$ 字符在(DI)-1=0002H的位置

Page 290: 第 3 章   8086 汇编语言程序设计

▲串指令可单独使用

MOV AL, [SI]

MOV ES:[DI], AL 等价于 MOVSB

INC SI

INC DI (假设 DF=0)

next: JCXZ exit

DEC CX

MOVSB 等价于 REP MOVSB

JMP next

exit: 、、

说明:

Page 291: 第 3 章   8086 汇编语言程序设计

下面程序段完成字传送 (8000:1000H) ← (4000:2000H)

MOV AX, 4000H

MOV DS, AX

MOV SI, 2000H

MOV AX, 8000H

MOV ES, AX

MOV DI, 1000H

MOVSW

Page 292: 第 3 章   8086 汇编语言程序设计

▲ 可在有源操作数的串指令前使用段跨越前缀, 此时:源串操作数的段值由段跨越前缀指定。 包括指令 MOVS 、 LODS 、 CMPS

例 : ES : MOVSB

执行 ( ES:DI ) ← (ES:SI)

而不是( ES:DI ) ← (DS:SI)

ES: SCASB 没有源串ES: STOSW

▲ 目的串操作数不允许使用段跨越前缀,即串指令前的段跨越前缀必指源串操作数。

Page 293: 第 3 章   8086 汇编语言程序设计

▲重复前缀中 CX 减 1 操作,不影响标志。

REPNZ执行流程

(CX)=(CX)-1

REPNZ后的串 指 令

Y

N

Y

N

CX=0 ?

ZF=0 ?

REP执行流程

(CX)=(CX)-1

REP后的串 指 令

Y

NCX=0 ?

(CX)=(CX)-1

REPZ后的串 指 令

Y

N

Y

N

CX=0?

ZF=1 ?

REPZ执行流程

Page 294: 第 3 章   8086 汇编语言程序设计

操作类型默 认段寄存器

是否允许段 跨 越 有效地址

取指令 CS 否 IP

以 BP做基址的 操 作 数

SS CS、DS、ES EA

直接寻址、以 BX做基址的 操 作 数

DS CS、SS、ES EA

堆栈操作 SS 否 SP

源 串 DS CS、SS、ES SI串操作 目的串 ES 否 DI

几种操作复习

Page 295: 第 3 章   8086 汇编语言程序设计

DSESSSCS

IP

数据暂存器

PSW 标志寄存器 执行部件控制电路

指令译码器

AXBXCXDX

AHBHCHDH

SIDIBPSP

ALBLCLDL

寄存器组

指令队列

总线接口控制电路

运算器

地址加法器

、、、指令 1

指令 2

指令 3

指令 4

、、、数据 1

数据 2

数据 3

、、、

地址总线 AB

数据总线 DB

控制总线 CB