第一章 概述 第一节 引言

215
1 第第 第第

Upload: brandy

Post on 23-Jan-2016

73 views

Category:

Documents


6 download

DESCRIPTION

微机系统原理及应用. 第一章 概述 第一节 引言. 从 8088 、 8086 到 80386 以上直至 奔腾 ,只有 16 位与 32 位的区分,没有本质区别。芯片的指令 80% 以上是完全相同的,芯片的实地址工作方式几乎完全一致,所以 8088 、 8086 是 Intel x 86 系列的基础,要学习 x86 系列的最好办法就是从 8088 、 8086 入手。 PC 机的存储器( M )容量很大,但基本存储单元的工作原理不变;存储器与 CPU 的接口原理、方法没有变。 本书从 8088 、 8086 入手学习 PC. 第一节 引言. 一、计算机中的数制 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第一章  概述 第一节  引言

1

第一章 概述第一节 引言

Page 2: 第一章  概述 第一节  引言

2

第一节 引言

从 8088 、 8086 到 80386 以上直至奔腾,只有 16 位与 32 位的区分,没有本质区别。芯片的指令 80% 以上是完全相同的,芯片的实地址工作方式几乎完全一致,所以 8088 、 8086 是 Intel x 86 系列的基础,要学习x86 系列的最好办法就是从 8088 、 8086 入手。

PC 机的存储器( M )容量很大,但基本存储单元的工作原理不变;存储器与 CPU 的接口原理、方法没有变。

本书从 8088 、 8086 入手学习 PC

Page 3: 第一章  概述 第一节  引言

4

一、计算机中的数制 (一)二进制数的基本特点 1. 具有两个不同的数字符号,即 0 和 1 。 2. 逢二进位。 任意一个二进制数可以按“权”展开

i21n

mi iB

m2mB...121B

020

nB121

nB...1n21nB2

(B)

10(7.75)221121021221

2(111.11)

Page 4: 第一章  概述 第一节  引言

5

(二) 16 进制数 1. 0 至 9 和 A 至 F 。 2. 逢 16 进位。

① 16 进制数转化为 2 进制数。

② 2 进制数转换为 16 进制数。

1001

16 (50)162163(32)

i16 16D(D)

1n

mi i

16(3AB)

00113 10

1010A

11

1011B

2)110011101010( 16(3AB)

81000

70111

91001.

30011

E1110

B1011

10001

1BE3.978)(01111)0011.1001111011011(

16

2

Page 5: 第一章  概述 第一节  引言

7

二、二进制编码字符是用若干位二进制编码的组合表示字符、数,这称为二进制编码。

(一)二进制编码的十进制数( BCD ) 计算机的输入与输出是用十进制表示

(二)字母与字符的编码 ASCⅡ :实用标准信息交换码,用 7 位二 进制编码,可表示 128 个字符。 用一个字节来表示一个 ASCⅡ 字符 0 至 9 的 ASCⅡ 码为 30H 至 39H 大写字母 A 至 Z 的 ASCⅡ 码为 41H 至 5AH 小写字母 a 至 z 的 ASCⅡ 码为 61H 至 7AH

(三) 汉字的编码 这个字符集中的任何一个图形、符号及 汉字都是两个 7 位字节表示的 ( 每个字节的 最高位置为 0 )。

P507P507

Page 6: 第一章  概述 第一节  引言

8

三、二进制的运算计算机可进行两种基本的算术运算:加法和减法。利用这两种方法就可以进行乘法、除法以及其它数值运算。

逻辑运算: 1. “ 与”运算 (AND) 3. “ 非”运算 (NOT)

2. “ 或”运算 (OR) 4. “ 异或”运算 (XNOT)

(一)二进制加法 它的运算规则如下: 0+0=0 例如: 0+1=1+0=1

1+1=0 进位 1

1+1+1=1 进位 1

(二)二进制减法 它的运算规则如下:

BABA

AA

BA

1100010111101

Page 7: 第一章  概述 第一节  引言

9

0-0=0 借位 1-1=0 例如: 1-0=1 0-1=1 借位

(三)二进制乘法 它的运算规则如下: 0*0=0 例如: 0*1=0

1*0=0

1*1=1

由于此乘法的重复性差 , 不便 于在机器中实现,现在下面 用另外两种方式将运算实现。

100111110010010111000100

1100001111111111

1111

1101

1111

Page 8: 第一章  概述 第一节  引言

10

1. 被乘数左移法 乘数 被乘数

部分积 1101 1111

乘数最低位 11110 为 1, 把被乘数 加部分积 , 再 把被乘数左移 乘数为 0 ,不加, 111100 被乘数左移 同上 1111000 同上 n*n2n 位 2n 位加法器

111111110000

1100001111110001001011

1111001111

Page 9: 第一章  概述 第一节  引言

11

2. 部分积右移法 乘数

被乘数 部分积 1101 1111 乘数为 1, 加被乘 数部分积右移 0, 不加部分积 右移 1, 加被乘数部分 积右移 1, 加乘数右移

2 个 n*n乘积 2n 位 此种方法只需要 n 位加法器。

10111111111110000

00111100

011110001111

0111001

11100101111

110011

Page 10: 第一章  概述 第一节  引言

12

(四) 二进制的除法 例如:

四、带符号数的表示法 ( 一 ) 机器数与真值 数有正、有负 , 那么负数的符号是怎么表示的呢? 通常一个数的最高位为符号位 , 若字长为 8 位 ,

000111

0

101

101

101

0111

101100011101

7D

Page 11: 第一章  概述 第一节  引言

13

为符号位。符号位用“ 0” 表示正,用“ 1” 表示负。 例如:

连用一个符号位在一起的一个数,称为机器数。 它的数值称为机器数的真值。在机器数中符号有三种 表示法:原码,反码和补码。 ( 二 ) 原码 正数的符号位用“ 0” 表示,负数的符号位用“ 1” 表示的 表示法称为原码。 例如:

符号值 数值 ( 三 ) 反码 正数的反码与其原码相同,负数的反码是它的正数按位

91210111101x

91210110101x

105x

105x

1x

0x

Y

Y

0011101

0011101

Page 12: 第一章  概述 第一节  引言

14

取反 ( 连同符号位 ) 而形成的。 例如:

注: 符号位 取反的部分

反码的特点: 1. “0” 有两种表示法 2. 8 位二进制反码所表示的数值范围为 +127-127 。 即 , 3. 当一个符号数由反码表示时,最高位为符号数。 当符号数为“ 0” 时,后面的七位为数值部分; 当符号数为“ 1” 时,后面的七位一定要把它们按位取反,

以 表示它的二进制值。

101111114

010000004

F

F

111111110

000000000

F

F

010000014Y

1)(2 1n 12 1n

Page 13: 第一章  概述 第一节  引言

15

( 四 ) 补码 : 正数的补码表示与原码相同; 负数的补码表示为它的反码,且在最后位(即最低位)加

1 所形成。 例如:

8 位带符号位的补码特点: 1. ;

2. 8 位二进制补码所表示值为 +127 -128 ; 3. 一个用补码表示的二进制数 当符号位为“ 0” 时,其余 7 位即为此数的真值;

当符号位为“ 1” 时,其真值为其余 7 位按位取反,且在最 低位处加 1 后最终所得的结果。 例如:

110011114

101111114

010000004

B

F

Y

000000000

111111110

000000000

B

F

Y

0000000000BB

N2N Yn

B

Page 14: 第一章  概述 第一节  引言

16

采用补码表示的目的在于可以把减法转换成加法。 补码的加法规则:

补码的减法规则: 。例如:

下面举一个钟表的例子:将钟从 10 点拨至 6 点有正拨、倒拨两种方式。既可倒拨 4 个小时,亦可顺拨 8 个小时。

10-4( 倒拨 )=10+8 ( 顺拨 ) 则 12 称为模。

BBBYXYX

BBBYXYX

011011111010100000100000010064

10[64][X]10][641064X

B

BBB

Page 15: 第一章  概述 第一节  引言

17

(10-4) 与 (10+8) 对模 12 是同余的, -4 与 +8 对模 12 互补。将两者分别用二进制加、减法计算释例:

自然丢弃 一般说来,若 Z=nK+Y(n 为整数 ) ,则称 Z 与 Y 对模 K 互补,记为ZY 。

001101100000101001000000

0011011011111011001000000

Page 16: 第一章  概述 第一节  引言

18

第三节 计算机基础

Page 17: 第一章  概述 第一节  引言

19

第三节 计算机基础一、计算机的基本结构

二、名词术语 1. 位 (Bit)

位是计算机所能表示的最基本最小的数据单元,位就是一个 二进制位,有 0 、 1 两种状态。

2. 字 (Word) 和字长 字是计算机内部进行的数据处理的基本单位,每个字的位数

为字长。 3. 字节 (Byte)

1Byte=8Bit三、指令程序和指令系统 指令 : 计算机执行的各种操作的命令的形式写下来的方式。

一条指令对应着一种操作。它由两部分组成:操作码字段和 操作数字段。 操作码表示计算机所要执行的操作;操作数表示参加 操作的数的本身或操作数所在的地址。

Page 18: 第一章  概述 第一节  引言

20

指令的格式为

一地址 二地址

8088 指令的格式大多数为双操作指令。因为计算机只识别二进制数 , 所以计算机的指令系统中的所有指令都必须以二进制编码的形式来表示,这就是指令的机器码。例如 数据传送指令mov AL,7它的二进制机器码为 1011 0000 (mov AL,n) 0000 0111 ( n=7 )用助记符来表示操作码 , 用符号或符号地址来表示操作数地址的方式 称为汇编语言,它与机器指令是一一对应的。( 例如 Mov,Add,Jmp等指令 )当机器开始执行程序 ,给 PC 程序计数器赋以程序第一条指令所在的地址 , 然后每取出一个指令 ,PC 中的内容自动加 1 ,并指向下一条指令的地址 , 以保证指令顺序执行。值得注意的是只有在执行Jmp,Call,Interrupt 时 ,PC才转到所需要的地方。

操作码 操作数 ...操作数 ...

Page 19: 第一章  概述 第一节  引言

21

四、模型机 ( 一 ) CPU 结构 (P18 如图 1-9 1-10) ( 二 ) 存储器

不同二进制数 地址 内容

00H 01H

DB FFHCPU控制 信号

注意:每一个存储单元的地址和这个地址中存放的内容是 完全不同等概念 ,千万不能混淆。

确定单元后就可以对这个单元的内容进行读或写的操作。 下面举例说明: 1. 读操作

地址译码器

00H 单元01H 单元

FFH 单元

控制器

.

.

Page 20: 第一章  概述 第一节  引言

22

将 04H 单元格中的内容读出送至 DR( 数据寄存器 ) 。 内容

AR 00H

04H

04H

FFH DB

地址译码器

00H 单元

1000 0100

FFH 单元

84H

控制器

Page 21: 第一章  概述 第一节  引言

23

2. 写操作 AR 内容 00H DR

10H FFH DB 写 ( 三 ) 执行过程 简单说来就是取指令加执行指令。当机器开始执行指令时 , 把第一条指令所在地址赋给 PC, 然后就进入取指阶段 , 在取 指阶段从内存中读出的内容必为指令 , 由 DR 把它送至 IR,然 后由指令译码器译码。 开始执行将第一条指令的地址送 PC 取指读内存 ( 由 DR) IR ID 译码 PLA

地址译码器

00H

0010 0110

FFH26H

控制器

10H

Page 22: 第一章  概述 第一节  引言

24

取指的基本格式为

在一条指令执行完以后就可以立即执行下一条指令 , 减少了 CPU为等待的时间 ,提高了运行速度。8088CPU功能上分为 BIU 和 EU, 即分别是总线接口和执行单元。 它们可以重叠。举例:把两个十进制数 7 和 10 相加。 Mov AL, 7 Add AL,10 HLT 第一条指令 1001 0000(Mov AL, 7) 0000 0111 ( n=7 )

取指

取指取指

取指

取指

执行

执行

执行 执行

执行 …...

…...

…...

取指

等待

Page 23: 第一章  概述 第一节  引言

25

第二条指令 0000 0100 (ADD AL, n) 0000 1010 ( n=10 ) 第三条指令 1111 0100 ( HLT ) 三条指令 5 个字节。 将三条指令放入存储器,若是从 00H 开始的存储单元。 二进制 地址 ( 十进制数 ) 内容 0000 0000 00 mov AL,7 0000 0001 01 n=7 0000 0010 02 Add AL,7 0000 0011 03 n=10 0000 0100 04 HLT 取第一条指令 取立即数 取第二条指令 取第二条指令第二字节及执行指令的过程

五、软件

1011 00000000 0111

0000 10100000 0100

1111 0100

Page 24: 第一章  概述 第一节  引言

26

各种语言和它们汇编、编译、解释程序。 机器的监控管理程序 (Moniter),调试程序 系统软件 (Delug),故障检查 ,诊断程序。 程序库。 操作系统。 软件 应用软件 : 编制解决用户所碰到的各种实际问题的程序。 数据库及数据管理系统

由机器提供 , 为了使用和管理计算机

Page 25: 第一章  概述 第一节  引言

27

第四节 Intel 8088 的结构

Page 26: 第一章  概述 第一节  引言

28

Intel 8088 的结构 CPU: 准 16 位微处理器

DB : 8 条 AB : 20 条 采用 40 条引线封装 电源 +5V 1M直接寻址

一、 8088 的寄存器结构 寄存器:由多个触发器可以组成一个多位寄存器。 存储器:看作是一个寄存器堆,每个存储单元实际相当于一 个缓冲寄存器。二、 8088存储器 8088 有 20 条地址总线 , 220=1M,( 210 =1K), 地址从 00000FFFFF 。 其寄存器为 16 位 ,8088 对地址的运算只能是 16 位 ,寻址范围是 0000 FFFFH 。 1M存储器以 64K 为范围分为若干段。 00000 , 00001 ,… . 0000E , 0000F ; 64K 个行 00010 , 00011 ,… . 0001E , 0001F ;

00020 , 00021 ,… . 0002E , 0002F ;

202

Page 27: 第一章  概述 第一节  引言

30

00000 , 00001 ,… . 0000E , 0000F ; 00010 , 00011 ,… . 0001E , 0001F ;

00020 , 00021 ,… . 0002E , 0002F ; 64K 个行

FFFF0, FFFF1, …. FFFFE, FFFFF

16 个列 00000H 由于它为小段的首地址 , 其低 4 位一定为 0

00010H 段地址只取段起始地址高 16 位。 64K 个 这样 , 每一个存储单元都有唯一的 20 位地

段首地址 42230H 址 , 此地址称为该存储单元的物理地址。 42240H 0000 ( 左移 4 位 )

+

FFFE0H

FFFF0H

16 位段地址16 位偏移地址

20 位物理地址计算方法

Page 28: 第一章  概述 第一节  引言

31

16位段地址存放在段寄存器中,偏移量存放在 IP、 SP、DI、 SI、BP(基数 )中。当取指令时 CS的地址 +IP的 16位偏移量 =要取的指令的物理地址 当堆栈操作时 SS的地址 +SP的 16位偏移量 =堆栈操作的 20位物理地址 当涉及到操作数时 在不改变段寄存器在不改变段寄存器 DS或ES地址 +16位偏移量 的情况下的情况下 ,,寻址最大寻址最大

=操作数的 20位物理地址 范围是范围是 64K64K 。。 64K 代码段 64K 堆栈段

64K 数据段 64K 附加数据段

CSSSDSES

Page 29: 第一章  概述 第一节  引言

34

第一节 8088 的寻址方式

Page 30: 第一章  概述 第一节  引言

35

一、指令的格式

寻找操作数的方式称为寻址方式。 1. 操作数包含在指令中 , 即指令的操作数场就包含在操作数本

身中。此寻址方式称为立即寻址 , 这种操作数就称为立即数。 2. 操作数包含在 CPU 的某一内部寄存器中 , 这种寻址方式称为 寄存器寻址。 3. 操作数在内存的数据区中 , 此时指令中的操作数场包含着此 操作数的地址。 存储单元所在基地址 ( 段寄存器 )

8088 内存地址 段内偏移量 EA 指令的操作数场中规定的地址就是这个段内偏移量,又称为

有效地址 EA 。 EA 的构成有以下 5 种:

直接地址:包含在指令中的 16 位地址偏移量构成 EA ————直接寻址方式

操作码 操作数 操作数 …...

Page 31: 第一章  概述 第一节  引言

36

间接地址: EA 由 CPU 内某一个寄存器的 16 位内容构成 ————间接寻址方式 基址方式:基址寄存器 BX 或 BP 加上指令中的包含 8 位或 16 位位移量构成 EA ———— 基址寻址方式 变址方式:由变址寄存器 DI 或 SI 和包含指令中的 8 位或 16 位

位移量构成 EA

————变址寻址方式

基址加变址方式:由一个基址寄存器 BX 或 BP 加变址寄存器 SI 或 DI 再加包含指令中的一个 8 位或 16 位 位移量构成 EA

————基址加变址寻址方式一、立即寻址

此方式所提供的操作数 例如 直接放在指令中 ,紧跟在 mov AX,im 操作码一起放在码段区 域中。

AH ALimHimL

Page 32: 第一章  概述 第一节  引言

37

立即寻址主要用来给寄存器赋初值。 二、直接寻址 操作数的地址的 16 位偏移量直接包含在指令中 , 它与操作码

一起被放在码字段区域中 ,但操作数一般在数据段。它的地 址为数据段寄存器 DS 加上它 16 位地址偏移量。 例如: mov AX,[2000H]

注意:在例题中我们遇到的 [2000H] 。当我们用 AXBX 或 AXBX 时 , 表示将 AX 中的内容送 BX 或将 BX 中的内 容送 AX 。而用 AX[BX] 或 AX[n], 表示 [ ]中的是操

30 00 0

DS

20

数据段

码段

操作码00H20H

50

低高

3000032000

ALAHAX

32000H200030000

Page 33: 第一章  概述 第一节  引言

38

作数地址 , 把此地址单元的内容 ( 操作数 ) 送至 AX 中。 物理地址 =16d DS+EA 三、寄存器寻址

操作数包含在 CPU 内部寄存器中 , 如 AX 、 BX 、 CX 、 DX 。 例如 已知 AX , BX ,求执行程序后的 A

X 。 mov AX, BX 四、寄存器间接寻址

其操作数是在存储器中 , 操作数的地址 16 位偏移量包含在 SI 、

DI 、 BX 、 BP之一中。 ( 一 ) 以 SI 、 DI 、 BX间接寻址 其操作数在数据段区域中 物理地址 =16d(DS)+BX 或 SI 或 DI

( 二 ) 以寄存器 BP间接寻址

30 64 12 34

3412最终 AX

Page 34: 第一章  概述 第一节  引言

42

其操作数在堆栈段区域中 物理地址 =16dSS+BP 五、变址寻址

变址寻址是以指定的寄存器内容加上指令给定的 8 位或 16 位 位移量和段地址作为操作数的地址。 物理地址 =16d(DS) + (BX) + 8 位或 16 位位移量

或 (SI) 或 (DI) 或 = 16d(SS) + (BP) + 8 位或 16 位位移量 六、基址加变址的寻址方式

8088 常把 BX 、 BP看作基址寄存器 , 把 SI 、 DI看作变址寄存器。 寻址方式:一个基址寄存器的内容 +变址寄存器的内容 + 指令中 8 位或 16 位位移量 + 段地址

物理地址 =16d(DS) +(BX) + (SI) + 8 或 16 位位移量 或 (D

I) 或 =16d(SS) + (BP)+ (SI) + 8 或 16 位位移量 或 (DI)

Page 35: 第一章  概述 第一节  引言

43

在正常情况下 , 由基地址决定哪一个段寄存器作为地址指针。 用 BXDS , BPSS 。

Page 36: 第一章  概述 第一节  引言

44

第二节 8088 中的标志寄存器

Page 37: 第一章  概述 第一节  引言

45

1. 辅助进位标志 A 在字节操作时 , 则由低半字节 ( 一个字节的低 4 位 )向高半字节有 进位或借位; 在字操作时 , 低位字节向高位字节有进位或借位 , 则 A=1, 否则 A=0 。 此标志用十进制算术运算指令中。2. 进位标志 C 当结果的最高位产生一个进位或借位 , 则 C=1, 否则 C=0 。主要 用于多字节数的加法、减法 , 移位和循环指令也能够把存储器 或存储器中的最高位 ( 左移 ) 或最低 ( 右移 )放入 C 中。3. 溢出标志O 在算术运算中 , 带符号数的运算结果 , 如果超出以下范围:

字节 字 则 O=1, 否则 O=0 。溢出和进位是两个不同的概念。 溢出判断:

15Z

0CDO PAT SI

8 7

27 127 215 1215

Page 38: 第一章  概述 第一节  引言

47

同号相加 , 若结果的符号位相反 , 则溢出。 异号相减 , 若结果的符号位与被减数相反 , 则溢出。4. 符号标志 S S 的值与运算结果的最高位相同 , 若最高位为 1, 则 S=1 ,否则 S=0 。 由于 8088 中 , 符号数是用补码表示的 , S=0 为正 , S=1 为负。5.奇偶标志 P 若操作数结果中“ 1” 的个数是偶数 , 则 P=1, 否则 P=0 。6. 零标志 Z 若运算的结果为 0, 则 Z=1, 否则 Z=0 。7. 方向标志 D 若用指令置 D=1, 则引起串操作指令为自动减量指令;

若用指令置 D=0, 则引起串操作指令为自动增量指令。 8. 中断允许标志 I

若指令中置 I=1, 则允许 CPU去接收外部的可屏蔽的中断请求;

若指令中置 I=0, 则屏蔽上述的中断请求。 I 对 CPU 内部产生的中断不起作用。9. 追踪标志 T

Page 39: 第一章  概述 第一节  引言

48

补充内容:操作码和寻址方式的机器语言表示方法 操作码的机器语言表示

W 位 是指示本指令是对字 (W=1)还是对字节 (W=0) 操作; d 值 在双操作数指令中才有效。 8088 指令规定双操作数指  令的两个操作数必须有一个操作数放在寄存器中;   d 位 指定寄存器用于目的操作数 (d=1)还是源操作数 (d=0)   (8 16 ,高位字节按低位字节的最高有效位作符号扩展 ) 。  当立即方式寻址时,S位表示符号扩展  当指令字节操作时, SW=00;  当指令有 16 位立即数且作字操作时, SW=01 ;  当指令有8位 ,但需要经符号扩展成 16 位 ,立即数作字操作时 ,  则 SW=11 。 寻址方式的机器语言表示   8088 用一个字节表示操作数的确寻址方式  它通常是机器指令的第二个字节

op Wd

Page 40: 第一章  概述 第一节  引言

49

表示为

在双操作数指令的情况下规定必须有一个操作数在寄存中 ,该 寄存器由 reg 字段指定。 mod 与 r/m 是另一种操作数寻址方式。 mod=11, 为寄存器方式 , 由 r/m 的内容确定选用哪个寄存器; mod=00, 为元位移量字节的存储器寻址方式——直接寻址; mod=01, 为带一个位移量字节的存储器寻址方式; 指令中应有

mod=10, 为带两个位移量字节的存储器寻址方式;

如果出现段跨越 , 则必须加 001 , 再加上 110 。

操作数在

存储器中

D8

mod r/mreg

01 r/mreg

10 r/mreg

D16 高位

D16 低位

间接寻址

SEG

Page 41: 第一章  概述 第一节  引言

50

上面的寻址方式是指无段跨越前缀的情况下所用的隐含的段 寄存器 , 如果指令中指定段跨越前缀 , 则在机器语言中使用放在 指令之前的一个字节来表示 , 如下:

001 110segsegment 00

011011

ESCSSSDS

SEG

Page 42: 第一章  概述 第一节  引言

51

置 T标志 , 使处理进入单步方式 , 以便于调试。在这个方式 , CPU 在每条指令执行以后产生一个内部的中断 , 允许程序在每条执 行完以后进行检查。

Page 43: 第一章  概述 第一节  引言

52

第三节 8088 的指令系统

Page 44: 第一章  概述 第一节  引言

53

8088 的指令系统可分成 6 个功能: • 数据传送 •算术运算 •逻辑运算 •串操作 •控制传送 •处理器控制

指令符号:8 位寄存器 AH,AL; BH,BL; CH,CL; DH,DL16 通用寄存器 AX ; BX ; CX ; DX SP ; BP ; DI ; SI 堆栈指针 SP指令指针 IP ( 指向下一次要取出的指令 ) 或 PC( 指向下一条即将要执行的指令 )标志位 F目的和源变址寄存器 DI 、 SI

Page 45: 第一章  概述 第一节  引言

54

段寄存器 CS 、 DS 、 SS 、 ES通用寄存器 rAL 或 AX a源和目的操作数 src dst (存储单元 ) [ BX+SI+n ] [ BX+DI+n ] [ BP+SI+n ] [ BP+DI+n ] [ SI+n ] [ DI+n ] [ BP+n ] [ BX+n ] [ n ]---------- 直接 r ---------- 寄存器源操作数地址 ADR ( src)存储单元的内容 [ ]OPRD 操作数

Page 46: 第一章  概述 第一节  引言

55

附加存储器段的内容 ES[ ] 段寄存器 seg 立即数 im 8 位 n 16 位 nn 32 位 nnnn 一、数据传送指令 分为 4 种: • 通用传送指令 • 累加器专用传送指令

• 地址—目的传送指令 • 标志传送指令 此类指令 , 除了标志寄存器传送 SAHF 和恢复标志寄存器 POPF 指令以外 , 对标志位无影响。 ( 一 ) 通用传送指令 此指令是唯一允许以段寄存器作为操作数的指令。 (XCHG 除外 )

1. Mov OPRD1, OPRD2目的 源

Page 47: 第一章  概述 第一节  引言

56

它把一个字节 B 或字 W 操作数从源地址传送至目的地址。

它能实现以下 4 种数据传送: CPU 内部寄存器之间传送 ( 除 CS 和 IP 以外 ) 如

立即数传送 CPU 内部通用寄存器组给寄存器赋初值。 如 mov CL, 4 mov SI, 057BH

mov [nn], a B/W [nn]=amov a, [nn] B/W a=[nn]mov seg, src W seg=srcmov dst, seg W dst=segmov r, src B/W r=srcmov dst, r B/W dst=rmov r, im B/W r=immov dst, im B/W dst=im

mov AL, BLmov CX,BXmov DS,BXmov DX,ESmov SI,BP

Page 48: 第一章  概述 第一节  引言

57

CPU 内部寄存器 ( 除 CS 和 IP 以外 ) 与存储器之间的传送

() 通用寄存器与存储器之间 如 mov AX, [SI]

mov [DI], CX 寄存器间接 mov SI, BLOCK[BP] 变址 () 段寄存器 ( 除 CS 外 ) 与存储器之间

如 mov DS, DAT[SI+BX] seg M mov DEST[BP+DI], ES 注意: mov 指令不能实现存储单元之间的数据传送 , 也不允许 两个段寄存器之间直接传送。 若需要把地址 ( 段内地址位移量 ) 为 ARE1 的存储单元的 内容 , 传送至同一段内的地址为 ARE2 的存储单元可以 用 CPU 内部寄存器为桥梁来完成。 如 mov AL, ARE1 mov ARE2, AL

如 mov BX, offset TABLE

通用 rMseg M

Page 49: 第一章  概述 第一节  引言

58

把 TABLE 的偏移地址而不是内容送到 BX寄存器。 若传送 100 个数据

mov SI, OFFSET AREA1 mov DI, OFFSET AREA2 mov CX, 100 AGAIN: mov AL, [SI] mov [DI], AL INC SI INC DI DEC CX JNZ AGAIN

其中 OFFSET AREA1 是指地址单元 AREA1 在段内地址偏移量。 又如 mov AX, Y[BP][SI] 地址 16d(SS)+(BP)+(SI)+Y 的存储单元的内容送给 AX 。 其中 OFFSET 为属性操作符 , 表示应把其后跟着的符号 地址的值 ( 不是内容 ) 作为操作数。能实现用立即数给存储单元赋初值 (Mim) 如 mov mask [BX] [SI], 2CH

Page 50: 第一章  概述 第一节  引言

59

2. 堆栈操作指令 在主程序中往往要调用子程序或要处理中断就要暂停主程序 的执行 , 转去执行子程序 (中断服务程序 ), 则机器必须把主程序 中调用子程序指令的下一条指令 , 若第 X1 条指令为调用子程序 ,则它的下一条指令为 X2 的地址 , 即 PC 或 IP保留下来才能保 证当子程序执行完成以后返回主程序继续执行。另外 , 还必须 保留调用子程序的主程序的中间结果标志位的状态。

口诀:先进后出 , 后进先出。

8088中规定堆栈设置在堆栈段 (SS) 内 , 用堆栈指针 SP始终指向堆栈的 顶部 , 即始终指向最后推入堆栈的 信息所在的单元。 SP的初值规定 了所用堆栈的大小 , 8088中所设置 的 SP的初值 , 逐渐靠近 SS ,堆栈的 最大容量为 SP的初值与 SS间的距             离。入栈指令 它是把一个字的源操作数 , 送至栈的顶部。  

执行子程序

主程序

转向子程序

通用主程序

X1

X2IP

Page 51: 第一章  概述 第一节  引言

60

   PUSH OPRD(W)  在传送数据前 SP-2SP  具体指令如下:   PUSH r w SP=SP-2, [SP]=r PUSH    seg w SP=SP-2, [SP]=seg PUSH src w SP=SP-2, [SP]=src 源操作数可以是 CPU 的内部寄存器 , 段寄存器 ( 除 CS 外 ) 内存操 作数。出栈指令  POP OPRD(W) 在传送数据后 SP+2 SP 把现行 SP 指向的堆栈顶部的一个字 , 送至指定的目的操作数 , 然 后再进行修改指针 , SP+2 SP 。

 具体指令如下:   POP r w r=[SP] SP=SP+2 POP seg w seg=[SP] SP=SP+2

POP dst w dst=[SP] SP=SP+2 注意:堆栈是“后进先出”方式工作的 ( 一个 )存储区。它必须      在于堆栈段中 , SS存放段地址。 进栈:先移指针 , 后放入内容。出栈:先拿内容 , 后移指针。

Page 52: 第一章  概述 第一节  引言

61

PUSH AX         指令分两步执行:

PUSH BX     第一步: SP-1 SP

然后把 AH(寄存器中的高位字节 ) 送至 SP 所指的单元;          第二步: SP-1 SP 然后把 AL(寄存器中的低位字节 )              送至 SP 所指的单元。              如  PUSH AX 

                        

ALBH

AH

BL

SP SP-1 SP-1

SS

低址 SP

低地址

指令执行前高地址

低地址SP

指令执行后高地址

0721

(AX)=2107H

Page 53: 第一章  概述 第一节  引言

62

出栈指令举例 如  POP AX

SP低地址

指令执行前高地址

2107

SP

低地址

指令执行后高地址

2107

出栈方向

(AX)=2107H

Page 54: 第一章  概述 第一节  引言

63

3. 交换指令 XCHG OPRD1 , OPRD2 目的操作数 源操作数

把一个字节或一个字的源操作数与目的操作数相交换。 rAX, r r, r M 段寄存器不能作一个操作数。 具体指令如下: XCHG AX , r w r=AX, AX=r XCHG r , src B/w r=src, src=r

( 二 ) 、累加器专用传送指令 1. IN 输入指令 把一个字节或一个字由一个输入端口 (Port) 传送至 AL或 AX 。 端口地址若是由指令中的 n(8 位 ) 所规定 则寻址 Port0Port255, 共 256 个输入端口。 端口地址若是由寄存器 DX 规定 则寻址范围 64K 个输入端口 (8088 采用间接寻址方式, I/O端口地址可扩展到 64K) 具体指令如下:

Page 55: 第一章  概述 第一节  引言

64

IN AL, n B AL=[n] IN AX, n W AX=[n+1][n] IN AL, DX B AL=[DX] IN AX, DX W AX=[DX+1][DX] 2. OUT 输出指令 把 AL 中的一个字节或 AX 中的一个字 , 传送至一个输出端口。 具体指令如下: OUT n, AL B AL [n] OUT n, AX W AX [n],[n+1] OUT DX, AL B AL [DX] OUT DX, AX W AX [DX],[DX+1] 3. XLAT查表转换 指令完成一个字节的查表转换 , 寄存器 AL 的内容 为一个 256 个字节的表的下标。这个表的基地址在寄存器 BX 中 , 转换后的一个字节的操作数放在 AL 中。 XLAT B (AL=[BX+AL]) (0 9 转换 7 段数码 )经常把一种代码转换为另一种代码。( 三 ) 、地址——目的传送

Page 56: 第一章  概述 第一节  引言

65

1. LEA 把源操作数的地址偏移量 , 传送至目的操作数。

LEA r, src r=ADR(src)

如 mov SI, OFFSET AREA1 等价于 LEA SI , AREA1 不等价于 mov AX, AREA12. LDS 此指令是传送一个目标指针 ( 段地址 + 地址偏移量 , 32 位 ) 从源操 作数 ( 为内存操作数 ) 传送至一对目的寄存器。 16 位地址偏移量 1 个 16 位的指针寄存器 (SP,BP) 或变址寄存器 (DI, SI) 目的段地址 DS寄存器 指令格式: LDS r, src DW r [EA] DS [EA+2]

内存操作数 16 位的通用寄存器

Page 57: 第一章  概述 第一节  引言

66

LDS 指令示意图: LDS

3. LES 除了把目标段地址送至段寄存器 ES 以外 , 其它与 LDS 指令类似。

LES reg, src r [EA], ES [EA+2]

操作码

2 个字节2 个字节

EA

DS

偏移量

SI

DI, BP,SP变址

Page 58: 第一章  概述 第一节  引言

67

举例来说 : 1. LEA BX, [BX+SI+0F62H]

指令执行前 (BX)=0400H, (SI)=003CH指令执行后 (BX)=0400+003CH+0F62H=139EH

BX寄存器得到的是偏移地址而不是该存储单元内容

2. LDS SI, [0010H]指令执行前 (DS)=C000H, [C0010H]=0180H, [C0012H]=2000H

指令执行后 (SI)=0180H, (DS)=2000H

3. LES DI, [BX]指令执行前 (DS)=B000H, (BX)=080AH [0B080AH]=05AEH, [0B080CH]=4000H

指令执行后 (DI)=05AEH, (ES)=4000H

Page 59: 第一章  概述 第一节  引言

68

( 四 ) 、标志寄存器传送 1. LAHF

2. SAHF 此指令与 LAHF 相反 , 是把 AH 的指定位送至 FLAG 中的 S 、Z 、 A 、 P 、 C 3. PUSHF

把 FLAG 中的 (全部 9 个标志 )推入栈堆指针所指的堆栈的顶 部。传送数据前 SP SP-2 。此指令不影响标志位。 4. POPF 把现行堆栈指针所指的一个字 , 传送至 FLAG 。 然后 SP+2 SP 。 PUSHF 和 POPF 可以保存和恢复标志寄存器。在子程序调用 和中断服务中可利用这两个指令。

15 0Z CPAS

7 06 4 2

O D I T

不影响 F

Page 60: 第一章  概述 第一节  引言

69

二、算术运算指令 2 进制运算可以是双操作数 , 10 进制运算可以是单操作数。

若是符号数用补码表示。 ( 一 ) 加法:共有 5 种。 1.ADD OPRD1, OPRD2 OPRD1+OPRD2 OPRD1 目的操作数 :累加器、通用寄存器、存储器操作数。 指令格式: ADD r, src B/W r+src r ADD a, im B/W a+im a ADD dst, im B/W dst+im dst ADD dst, r B/W dst+r dst

如: ADD AX, 3000H ADD AX, SI ADD SI, AX ADD AL, DATA[BX] ADD BETA[SI], DX ADD BETA[SI], 100

这些指令对 FLAG 中C 、 O 、 P 、 S 、 Z 、 A

有影响。

Page 61: 第一章  概述 第一节  引言

70

2. ADC 在两个操作数相加时 , 把进位标志 C 的值加上去 , 结果送至一个 操作数。 格式: ADC DST, SRC (DST) (SRC)+(DST)+C 具体如下: ADC r, src r+src+c r ADC a, im a+im+c a ADC dst, im dst+im+c dst ADC dst, r dst+r+c dst ADC主要用于多字节运算 , 先进行低两字节相加 , 然后进行高两 字节相加 , 若两个四字节的数相加 , 分别放在 FIRST 和 SECOND

存储区中 , 每个数占四个存储单元。最低字节在地址最低处。

如:

Mov AX, FIRSTAdd AX, SECONDMov THIRD, AXMov AX, FIRST+2Adc AX, SECOND+2Mov THIRD+2, AX

也影响 FLAG 中C 、 O 、 P 、 S 、 Z 、 A

Page 62: 第一章  概述 第一节  引言

71

3. INC 格式: INC OPR (OPR) (OPR)+1 完成对指定的操作数加 1, 再返回此操作数。 影响标志位 A 、 O 、 P 、 S 、 Z 。不影响标志位 C 具体如下: INC r W r+1 r INC src B/W src+1src4. AAA 加法的 ASCII调整指令 ( 非压缩 BCD) 。。 执行这条指令之前必须执行 ADD 或 ADC 指令。加法指令把两 个非压缩 BCD 码相加 , 结果放在 AL 中。 执行的操作:

AL把 AL 中的和调整非压缩 BCD 格式 AH AH 加调整产生的进位值 ( 对应步骤中的 )

以下是具体步骤: 如果 AL 的低 4 位在 09之间 , 且 A=0, 则跳过 , 执行;

如果 AL 的低 4 位在 AF之间或 A=1, 则 AL 加上 6, 且 A=1 ;

Page 63: 第一章  概述 第一节  引言

72

清除 AL 的高 4 位 (AL&0FH) ; AHAH+1 A 的值送至 C 。 AAA影响标志位 C 、 A 。

例如 ADD AL, BL AAA 执行前 AX=0535H , BL=39H

可见 AL 、 BL 的内容分别为 5 和 9 的 ASCII 码

执行完第一条指令后(AL)=6EH A=0

执行完第二条指令后ASCII调整后 (AX)=0604H 6E+06=74H A=1, C=1

5. DAA 加法的十进制调整指令 (压缩 BCD) 。 在执行此指令之前 , 先执行 ADD 或 ADC 加法指令。必须把两个压 缩的 BCD 码相加 , 结果放在 AL 中。

Page 64: 第一章  概述 第一节  引言

73

调整方法如下: ( 参见 P82 例 ) 若 A=1, 或 AL 低 4 位是 A F, 则 AL+06HAL, 且 A=1 ;若 C=1, 或 AL 高 4 位是 A F, 则 AL+60HAL, 且 C=1 。

( 二 ) 减法指令 1.SUB ( 减法指令 ) SUB OPRD1, OPRD2 (OPRD1)(OPRD1)-(OPRD2) 具体形式如下: SUB r, src B/W r-src r SUB a, im B/w a-im a

例 ADD AL, BL DAA 执行前 (AL) =28H, (BL)=68H

第一条指令执行后 (AL)=90 C=0, A=1第二条指令执行后 因为 A=1, 所以 (AL) (AL)+06 得 (AL)=96 C=0, A=1

1001 0110

0110 1000

1001 0000A=1

0010 1000

0000 0110

9 6

+

+

Page 65: 第一章  概述 第一节  引言

74

SUB dst, r B/W dst-r dst

SUB dst, im B/W dst-im dst 此指令影响标志为 A 、 C 、 O 、 P 、 S 、 Z 。2. SBB ( 带借位减法指令 )

SBB OPRD1, OPRD2 (OPRD1)(OPRD1)-(OPRD2)-C 具体形式如下: SBB r, src r-src-C r SBB a, im a -im-C a SBB dst, r d st-r-C dst SBB dst, im dst-im-Cdst 此指令影响标志位 A 、 C 、 O 、 P 、 S 、 Z 。3. DEC ( 减 1 指令 )

DEC OPR 把操作数作为无符号数 2 进制数处理 (OPR) (OPR)-1 此指令影响标志位 A 、 O 、 P 、 S 、 Z, 不影响 C 。 OPR 可以是 r, 也可以是 M 。4. NEG (求补指令 ) NEG OPR (OPR)0FFFFH-(OPR)+1

Page 66: 第一章  概述 第一节  引言

75

即把操作数按位求反 , 末位加 1, 因而亦可表示。 此指令影响 A 、 C 、 O 、 P 、 S 、 Z 。注意:只有当操作数为“ 0” 时 ,求补运算结果使 C=0, 其它情况 C=1 。

5. CMP (比较指令 ) CMP OPR1, OPR2 (OPR1)-(OPR2) 完成两个操作数相减 , 并使结果反映在标志位上 , 不回送。 具体形式如下:

CMP r, src CMP a, im CMP dst, r CMP dst, im 比较指令主要用于比较两个数之间的关系 , 即两者是否相等 , 或 两个中哪个大 , 指令通过比较结果置标志位 , 表示操作数的关系。

下面以 CMP A, B 为例: 若两个操作数相等 即 A=B 则比较后 Z=1, 否则 Z=0 两个无符号数判大小

Page 67: 第一章  概述 第一节  引言

76

若 AB, 则不会产生借位 , C=0 若 A<B, 则产生借位 , C=1 因此根据 C标志位来判断两个无符号数的大小。两个有符号数判断大小 要结合 O 、 S 两个标志位 (I) 若 A 、 B 为同号 (A 、 B>0 或 A 、 B<0) 则两数相减绝对值变小不会溢出 , 此时可用 S判断大小。 AB S=0 A<B S=1 (II) 若 A 、 B 为异号数 (A>0,B<0 或 A<0,B>0) 则两数相减有可能溢出

简化:若 SO=0 时 , A>B

若 SO=1 时 , A<B

AB S=0A<B S=1

无溢出 A>B S=1A<B S=0

有溢出

若 O=0 时 S=0 则 A>BS=1 则 A<B

S=0 则 A<BS=1 则 A>B

若 O=1 时

Page 68: 第一章  概述 第一节  引言

77

例 1 SUB [SI+0014H], 0136H

例 2 SUB DH, [BP+4]

执行前 (DS)=3000H, (SI)=0040H(30054H)=4336H

执行后 4336-0136

0100 0011 0011 0110

-0000 0001 0011 0110

0100 0011 0011 0110

+1111 1110 1100 1010

求补

1 0100 0010 0000 0000

补码时 , 借了模 10000H

(30054H)=4200HS=0, Z=0,C=0,O=0

执行前 (DH)=41H, (SS)=0000H (BP)=00E4H, (000E8)=5AH

Page 69: 第一章  概述 第一节  引言

78

例 3 若自 BLOCK 开始的内存中 , 有 100 个带符号数 , 要找出其中 的最大值 , 把它存放到MAX 单元。

执行后 41-5A

0100 0001-0101 1010

0100 0001+1010 0110

求补

1110 0111

补码时 , 借了位

(DH)=E7HS=1, C=1,O=0

Mov BX OFFSET BLOCKMov AX, [BX]Inc BXInc BXMov CX, 99

AGAIN:CMP AX, [BX] JG NEXT Mov AX, [BX]

Page 70: 第一章  概述 第一节  引言

79

NEXT: INC BX INC BX DEC CX JNZ AGAIN Mov MAX, AX HLT

Page 71: 第一章  概述 第一节  引言

80

6. AAS ( 减法的 ASCII调整指令 , 非压缩 BCD) 执行的操作:

(AL) 把 AL 中的差调整到非压缩 BCD 格式 (AH) (AH)—调整产生的借位值 此指令之前必须执行 SUB 或 SBB 指令。

调整步骤如下: 如果 AL 的低 4 位在 09之间 , 且 A=0

则跳过执行 ; 如果 AL 的低 4 位在 AF之间或 A=1 则 AL-6 AL, AH-1 AH, 将 A=1 ;

清除 AL 的高 4 位 (AL AL&0FH) ; A 的值送至 C 。

AAS影响标志位 A 、 C, 其余标志位无定义。7. DAS ( 减法的十进制调整指令 , 压缩 BCD) 执行的操作: (AL) 把 AL 中的差调整到压缩的 BCD 格式 此指令之前必须执行 SUB 或 SBB 指令。

Page 72: 第一章  概述 第一节  引言

81

调整方法: 若 A=1 或 AL 的低 4 位是 AF

则使 AL-06H AL, 且 A=1 ; 若 C=1 或 AL 的高 4 位是 AF 则使 AL-60H AL, 且 C=1 。 DAS影响 A 、 C 、 S 、 Z 、 P, 对 O无定义。 例如 SUB AL, AH 执行指令 (AL)=86H, (AH)=07H

执行 SUB (AL)=7FH, C=0,A=1

执行 DAS 因为 A=1, 所以 (AL)=(AL)-06H=79 C=0, A=1

( 三 ) 乘法指令 8088 中有三条乘法操作指令 1.MUL (无符号数乘法 ) 格式: MUL SRC 执行的操作: (AX) (AL)*(SRC) 字操作数 : (DX, AX) (AX)*(SRC) 相乘时的另一操作数可以是寄存器操作数或内存操作数。

Page 73: 第一章  概述 第一节  引言

82

若结果的高半部分 (AH, DX) 不为 0 则标志 C=1,O=1; 否则 C=0, O=0 。 本指令对 A 、 P 、 S 、 Z无定义。2. IMUL( 带符号数乘法 ) 格式 : IMUL SRC 执行的操作:与 MUL 相同 , 但必须是带符号数 , 而 MUL 是无符 数。 对于 IMUL 指令 , 如果乘积的高一半 (AH, DX) 是低一半的符号 扩展 , 则 C=0, O=0; 否则 C=1, O=1. 那么所谓符号扩展是指一个数从位数较少扩展到位数较多的 数 (8 位 16 位; 16 位 32 位 ), 对于用补码表示的数 , 正数的符 号扩展应该在前而补 0, 而负数的符号扩展应该在前面补 1 。 [+46] 补 =0010 1110 [+46] =0000 0000 0010 1110 [-46] =1101 0010 [-46] =1111 1111 1101 00103. AAM( 乘法的 ASCII调整指令 ) 执行的操作: (AX) 把 AL 中的积调整到非压缩 BCD 格式 此指令之前必须执行 MUL 指令把两个非压缩的 BCD 相乘 ( 其高 4 位为 0) 结果放在 AL 中。

Page 74: 第一章  概述 第一节  引言

83

Page 75: 第一章  概述 第一节  引言

84

调整方法如下: AH AL/0AH (AL 被 0A 除的商 AH)

AL AL%0AH(AL 被 0A 除的余数AL) 如 6(0000 0110)7(0000 0111)——AL 积 (0010 1010) 则乘积的十进制数值的调整: 0000 0100 AH 0000 0010 AL( 四 ) 除法指令 1.DIV(无符号数除法指令 ) 格式为 DIV SRC 执行的操作: (AL) (AX)/(SRC) 的商 字节操作 (AH) (AX)/(SRC) 的余数 AX : 16 位 SRC : 8 位 (AX) (DX,AX)/(SRC) 的商 字操作 (DX) (DX,AX)/(SRC) 的余数 DX 、 AX : 32 位 SRC : 16 位 2. IDIV( 带符号数除法指令 )

Page 76: 第一章  概述 第一节  引言

85

此指令除了完成带符号数相除以外 , 与 DIV类似。 格式为 IDIV SRC

注意:对乘法、除法指令 SRC 不能为立即数。 除法指令对 A 、 C 、 P 、 Z 、 S 、 O 各种标志位均无定义。3. AAD( 除法的 ASCII调整指令 )

若被除数是放在 AX 中的二位非压缩 BCD , AH 中存放十位数。

AL 中放个位数。而且要求 AH 和 AL 高 4 位均为 0 ,除数是一 位非压缩 BCD ,要求其高 4 位为 0 。在这两个数用 DIV 指令以 前,必须先用 AAD 指令把 AX 中的被除数调整成二进制数,存 放在 AL 中。 调整操作: (AL) AH*0AH+AL (AH) 0 此指令影响 S 、 Z 、 P , 对 A 、 C 、 O 无定义。 4. CBW 格式为 CBW 执行的操作: AL 的内容符号扩展到 AH AL<80H , AH 0

Page 77: 第一章  概述 第一节  引言

86

AL80H , AH FFH 5. CWD 格式为 CWD 执行的操作: AX 的内容符号扩展到 DX AX<8000 , DX 0 否则 DX FFFFH三、逻辑运算指令 逻辑操作分为:单操作数操作 两个操作数操作 ( 一 ) 单操作数操作 1. 逻辑非指令

NOT src B/W (src 的反码 src) 2. 移位指令 格式 SAL 算术左移指令 SAL OPR, Count SHL 逻辑左移指令 SHL OPR, Count SAR 算术右移指令 SAR OPR, Count SHR 逻辑右移指令 SHR OPR, Count

Page 78: 第一章  概述 第一节  引言

87

OPR : 通用寄存器存储器操作数 (8 位或 16 位 )Count: 表示移位的次数。移位一次 count=1, 移位多次 count=CL. CL 为移位的次数。(1)SAL/SHL( 用一指令的两种表示方法 ) 在移位次数为 1 时 , 当新的操作数最高位与 C 不同时 , 则 O=1, 表明有符号数操作产生溢出 , 不再符合倍增关系。 对无符号数 , 当移位后使 C=1, 则不再符合倍增关系。

OPR

0

左移指令SAL SHL

C

OPR

算术右移SAR

C

OPR

逻辑右移SHR

C0

Page 79: 第一章  概述 第一节  引言

88

例 1 AL=0100 0010B 66 / +66

例 2 mov CL , 2 SHL SI , CL 已知 (SI)=1450H

左移一位 AL=1000 0100B 132 / (-124) , C=0, O=1

对无符号数 C=0 符合 662=132对有符号数 O=1 不符合倍增关系 +662=-124

执行指令前 (SI)=1450H 它的二进制形式是 0001 0100 0101 0000则执行指令后它的二进制形式是 0101 0001 0100 0000

另 执行指令前 (SI)=5200d 执行指令后 (SI)=20800d则 5200d 4d=20800d

Page 80: 第一章  概述 第一节  引言

89

(2) SAR( 算术右移 ) 指令常用于有符号数的减半运算。若右移使 C=1, 则减半结果 不精确。 (3) SHR( 逻辑右移 ) 本指令可以作为无符号数的除 2 运算 , 右移一位 , 相当数值下降 一级。若右移后 C=1, 表明移位前的数是奇数 , 减半结果不精确。 移位指令根据移位后的结果设置 S 、 Z 、 P , 对 A无定义。 3.循环指令 共有以下 4 个:

格式 ROL 循环左移指令 ROL OPR , COUNT

ROR 循环右移指令 ROR OPR , COUNT RCL 带进位循环左移指令 RCL OPR , COUNT RCR 带进位循环右移指令 RCR OPR , COUNT OPRD : 通用寄存器或存储器操作数 (8 位 / 16 位 )

COUNT :移位次数 移位 1次 COUNT=1 移位多次 COUNT=CL

Page 81: 第一章  概述 第一节  引言

90

循环移位指令不影响除 C 和 O 以外的其它条件标志。( 二 ) 两个操作数操作 1. AND 逻辑与指令 AND OPRD1 , OPRD2 B/W OPRD1OPRD1OPRD2 用于 : 两个数要保持不变的位和“ 1” 与 , 要置为“ 0” 的位和“ 0” 与。 2. TEST 测试指令 TEST OPRD1 , OPRD2 OPRD1OPRD2 完成与 AND 指令同样的操作 , 结果反映在表示位上 ,并不回

OPR

ROR

COPR

ROL

C

OPR

RCL

COPR

RCR

C

Page 82: 第一章  概述 第一节  引言

91

送目的操作数。通常用于检测一些条件是否满足 ,但不希望改 变原操作数。例如:

3. OR 或指令

OR OPRD1 , OPRD2 OPRD1OPRD1vOPRD2

TEST AL , 01HJNZ THERE

THERE

检测 AL 中的最低位是否为 1, 若为 1 则转移。

JZ 结果为零 ( 或相等 ) ,则转移 Z=1JNZ 结果不为零 ( 或不相等 ) ,则转移 Z=0

检测 CX 中的内容是否为 0, 若为 0 则转移。TEST CX , 0FFFFHJZ THERE

THERE

Page 83: 第一章  概述 第一节  引言

92

OPRD1 可以是累加器、寄存器、内存; OPRD2 可以是立即数、寄存器、内存。 “或”操作用于要求使一个操作数的若干位保持不变 , 而另外 若干位置为 1 的场合。保持不变的位和“ 0” 或 , 要置为“ 1”的位 和“ 1” 或。一个操作数和自身相“或” , 不改变其值 , 但C=0 。 ( 参看奇偶校验例题 ) 4. OR 异或操作 OR OPRD1 , OPRD2 OPRD1OPRD1OPRD2 当一个操作数对自身进行“异或”操作 , 结果为 0, C=0 。 常用于要置操作数初值为 0 的情况中。 ( 参看例题 ) 四、串操作指令 所有的基本的串操作指令 , 用 SI( 段地址寄存器为 DS)寻址 源操作数 , 用 DI( 对应的段寄存器为 ES) 为寻址目的操作数。 若 D=0, 则每次操作后 SI 和 DI增量 ( 字节操作加 1, 字操作加 2) ;

若 D=1, 则每次操作后 SI 和 DI 减量 1. 串传送指令 格式 MOVS OPRD1 , OPRD2

Page 84: 第一章  概述 第一节  引言

93

MOVS DST , SRC [ DI] [SI] 指针指示地址内容 MOVSB 字节操作 [ DI] [SI] SI SI1 DI DI1 当 D=0 时用加法 当 D=1 时用减法 MOVSW 字操作 [ DI] [SI] SI SI 2 DI DI 2 当 D=0 时用加法 当 D=1 时用减法 之前的传送 100 个操作数的例子可用上述指令改写为:

mov SI , OFFSET SOURCE mov DI , OFFSET DEST mov CX , 100AGAIN: movs DEST , SOURCE DEC CX JNZ AGAIN 又可以REP movs DEST , SOURCE (CX-1CX) 当 CX=0 时不重复

Page 85: 第一章  概述 第一节  引言

94

REP: CX=0 , 则退出 REP , 否则往下执行; CX-1CX ; 执行其后的串指令; 重复、。2. COMPS 串比较指令 格式 CMPS SRC , DST [SI]-[DI] CMPSB 字节操作 (SI) (SI) 1 (DI) (DI) 1 CMPSW 字操作 (SI) (SI) 2 (DI) (DI) 2 当 D=0 时用加法 当 D=1 时用减法 不保存结果 , 只根据结果置标志位。 ( 参看 例题 )

格式 REP MOVS MOVSB

MOVSW

Page 86: 第一章  概述 第一节  引言

95

3. SCAS 搜索串指令 格式 SCAS 串扫描指令

SCASB 字节操作 AL-[DI] (DI) (DI) 1 SCASW 字操作 AX-[DI] (DI) (DI) 2

AL 、 AX 、 [DI] 的内容并不改变。 而标志位 A 、 C 、 O 、 P 、 S 、 Z 反映 AL/AX 的值与串元素之间 的关系。 ( 参看 P102 例题 ) 4.LODS 从串取指令 格式 LODS SRC LODSB 字节操作 AL[SI] SISI1 LODSW 字操作

Page 87: 第一章  概述 第一节  引言

96

AX[SI] SISI2 当 D=0 时用加法 当 D=1 时用减法 5. STOS 存入串指令 格式

STOS DST STOSB 字节操作 [DI]AL DI DI 1 STOSW 字操作 [DI]AX DI DI 2 当 D=0 时用加法 当 D=1 时用减法 ( 参看 P103 例题 )

五、控制传送指令 ( 一 )调用 Call 、转移 JUMPS 、返回 returns 。 1. Call 格式 Call DST 1) 段内直接调用 操作:

Page 88: 第一章  概述 第一节  引言

97

SPSP-2 [SP+1 , SP] IP

IP (IP)+D16

指令的第一步:把子程序的返回地址 ( 即 Call 指令的下一条指令 的地址 )存入堆栈中 , 以便子程序返回主程序。

指令的第二步:转移到子程序的入口地址继续执行。 DST给出转向地址 ( 子程序的入口地址 ), D 为指 令中的位移量 , 它是转向地址和返回地址之间的 差值。2 )段内间接调用 操作: SPSP-2 [SP+1 , SP] IP

IP [ EA] 由 DST 的寻址方式所确定的有效地址3 )段间直接调用 操作: SPSP-2 [SP+1 , SP] CS

IP 指向下一次要取出的指令

16

Page 89: 第一章  概述 第一节  引言

98

SPSP-2 [SP+1 , SP] IP

IP 偏移地址 ( 指令的 2 、 3 个字节 ) CS 段地址 ( 指令的 4 、 5 个字节 )

4 )段间间接调用 操作: SPSP-2 [SP+1 , SP]CS

SPSP-2 [SP+1 , SP] IP

IP[EA ] CS [EA+2]

2. RET 返回指令 放在子程序的末尾 , 使子程序执行完后返回调用程序继续执行 , 返回地址是 Call 时存放在堆栈中。 1) 段内返回 格式 RET 操作:

Page 90: 第一章  概述 第一节  引言

99

IP[SP+1, SP] SP SP+2 2) 段内带立即数返回 格式 RET EXP 操作: IP[SP+1, SP]

SP SP+2 SP SP+D 由 EXP 的值计算出 D 。 此指令允许返回地址出栈后修改堆栈的指针 , 以便在调用程 序在用 call调用子程序以前把子程序所需要的参数入栈 , 以 便子程序运行时使用这些参数。当子程序返回后 , 这些参数 已不再使用了 , 可以修改指针使其指向参数入栈以前的值。 3) 段间返回 格式 RET 操作: IP[SP+1, SP]

SP SP+2

16

16

Page 91: 第一章  概述 第一节  引言

100

CS[SP+1, SP] SP SP+24) 段间带立即数 格式 RET EXP 操作: IP[SP+1, SP] SP SP+2 CS[SP+1, SP] SP SP+2 SP SP+D CALL, RET 不影响标志位 A 、 C 、 O 、 P 、 S 、 Z 。3. JMP 跳转指令 无条件转移指令 , 不要求返回。 1) 段内直接短转移 格式 JMP SHORT OPR 操作: IP IP+D (8 位偏移量 ) 2) 段内直接近 转移

16

8

Page 92: 第一章  概述 第一节  引言

101

格式 JMP NEAR PTR OPR 操作:

IP IP+D (16 位偏移量 ) 3) 段内间接转移 格式 JMP WORD PTR OPR 操作: IP (EA) 属性操作符 4) 段间直接转移 格式 JMP FAR PTR OPR 操作: IP OPR 的段内偏移地址 CSOPR 所在段的段地址 ( 二 ) 条件转移指令 条件转移指令是以某些标志位或其逻辑运算为依据。 若是满足所规定条件 , 则程序转移到指定目标 ; 若不满足条件 , 则程序顺序执行条件转移指令的下一条指令。 目标地址是采用相对寻址方式 , 即以转移指令为基准的 +127 或 -128 字节范围内寻址。

16

Page 93: 第一章  概述 第一节  引言

102

(1)根据标志位的条件转移指令 JCC=1 JNC C=0

JE/JZ 相等或结果为 0 , 即 Z=1 JNE/JNZ 不相等或结果非 0 ,即 Z=0

JS S=1 转移 JNS S=0 转移

JO O=1 转移 JNO O=0 转移

JP/JPEP=1 转移 JNP/JPO P=0 转移 (2) 用于无符号的条件转移指令 JA/JNBE 为 高于 / 不低于或等于时转移 即 ZVC=0 JNA/JBE 为 不高于 / 低于或等于时转移 即 ZVC=1 (3) 带符号数的条件转移 JG/JNLE 为 大于 / 不小于或等于时转移 即 (SO)VZ=0 JGE/JNL 为 大于或等于 / 不小于时转移 即 SO=0 JL/JNGE 为 小于 / 不大于或等于时转移 即 SO=1,Z=0

Page 94: 第一章  概述 第一节  引言

103

JLE/JNG 为 小于或等于 / 不大于时转移 即 (SO)vZ=1( 三 ) 重复控制 重复控制指令是当 CX 不为零时 ,循环至目的地址。 若 CX=0 时 , 则顺序执行重复控制指令的下一条指令。它的相 对寻址是在控制指令的 +127-128 字节的范围内。 1.LOOP CX-1CX 若 CX0 则循环到目标操作数—— IP+偏移量 (16 位 ) ; 若 CX=0 则退出循环 , 往下执行。 2.LOOPZ CX-1 CX 若 CX0 且 Z=1 则循环;否则退出循环。 3.LOOPNZ CX-1 CX 若 CX0 且 Z 1 则循环;否则退出循环。 4.JCXZ 若 CX=0 则转移到目标操作数—— IP+偏移量 (扩展到 16 位 )( 四 ) 中断

Page 95: 第一章  概述 第一节  引言

104

当系统运行或程序运行期间在遇到特殊情况 , 需要计算机自 动执行专门的程序来进行处理 , 这种情况称为中断。 它分为 2 种:

内部中断指令 , 除 0产生的中断 外部中断指令 , I/O 与 CPU 中断向量:中断程序的入口地址 03FF 单元 ,1024 个字节为中断向量区 , 存放 256 种类型 。每个 中断向量占有 4 个字节单元 , 分别是 CS(2 个 ) IP(2 个 ) 1.INT 中断指令

INT TYPE—— 中断类型号 ( 可以是常数或常数表达式 P335) 执行操作: SPSP-2 [SP+1 , SP]F SPSP-2 [SP+1 , SP] (CS) SPSP-2 [SP+1 , SP] (IP) (IP) [ TYPE*4 ] CS [ TYPE*4+2 ]

Page 96: 第一章  概述 第一节  引言

105

2. INTO 若溢出中断指令 格式 INTO 操作: 若 O=1 , 则 SPSP-2 [SP+1 , SP] F SPSP-2 [SP+1 , SP] (CS) SPSP-2 [SP+1 , SP] (IP) IP[0010H] CS[0012H] 3.IRET 从中断返回指令 格式 IRET 操作: IP [SP+1, SP] SPSP+2 CS[SP+1, SP]

SPSP+2 F [SP+1, SP] SPSP+2

型号 =4 的中断44=10H

4 4+2=12H12H 的一个字的内容 CS

Page 97: 第一章  概述 第一节  引言

106

六、处理器控制指令 ( 一 )标志操作 1. CLC C=0 2. CMC CC 3. STC C=1 4. CLD D=0 5. STD D=1 6. CLI I=0 7. STI I=1 ( 二 )CPU暂停

HLT ( 三 )CPU脱离 ESC——交权指令 ( 四 )CPU等待 Wait ( 五 )总线锁定 Lock

Page 98: 第一章  概述 第一节  引言

107

第一节 汇编语言语句

Page 99: 第一章  概述 第一节  引言

108

一、语句类别 汇编语言的基本语句: 指令语句 伪指令语句 宏指令语句 源程序是用汇编的语句编写的程序。 格式为 NAME1 Segment NAME1 ENDS NAME2 Segment

NAME2 ENDS

ENDS 指令语句格式为 [标号: ] 助记符操作数 1, 操作数 2 [ ;注释 ]

伪指令语句格式为

Page 100: 第一章  概述 第一节  引言

109

[ 符号名 ]定义符 参数 1……….. 参数 n [ ;注释 ] 宏指令语句格式为 [标号: ] 宏指令名 参数 1……….. 参数 n [ ;注释 ] 1. 标号表示一条指令所在地址 , 也是指令语句的地址符号 , 最多 允许使用 31 个字符。不能以数字开头。 符号名用在伪指令语句前面 , 不是每一条伪指令都必须有一个 符号名的。 2. 助记符及定义符由系统定义。 3. 宏指令名由程序员定义 , 但不能用系统已经定义过的符号名。 4. 操作数用于指令语句 , 参数用于伪指令和宏指令中。 5. 注释不是汇编语句的必须部分。

Page 101: 第一章  概述 第一节  引言

110

第二节 语句行的构成

Page 102: 第一章  概述 第一节  引言

111

一、标记 ( 一 ) 字符集:字母、数字、特殊字符 (+ 、 - 、 * 、 / 、 { 、;等 ) 。 ( 二 )界符 : , < - + >

( 三 ) 常量 1. 数字常量 : 二进制数、十进制数、八进制数、十六进制数 2. 字符串常量:由包含单引号内的 1 至 2 个 ASCII 字符构成。

( 四 )标识符 由程序建立的 , 由最多 31 个字母 , 数字及字符组成 , 且不能 用数字开头。 如 : MY_DATA , SUM

THIS_DONE 和 THISDONE 是不同的。 (五 )保留字:指令助记符 , 伪指令 , 寄存器名称。 (六 ) 注释二、符号 它是一种标识符 , 符合标识符的组成规则。 寄存器、变量、标号、数、其它。 ( 一 )寄存器: AX 、 AL 。

Page 103: 第一章  概述 第一节  引言

112

( 二 )变量 存放在存储单元的操作数是变量 , 存储单元的地址符号就是 它们的名字。 任何变量都有三种属性:

1. 段值 (segment) 2.偏移量 (offset):变量单元地址与段的地址之间的偏移量 (16 位 ) 3.类型 (type):B( 字节 ) 、 (W 字 ) 、 (DW 双字 )( 三 )标号 与变量相似 , 是存储单元的符号地址。 它在存储单元中存放指令 , 变量存放数据。 类型 : FAR(CS 、 IP) 或 NEAR(IP)( 四 ) 数 源程序的常数 , 常以符号形式出现 , 便于修改。 如 Count EQU 100 又如 把端口地址定义为一个符号 PORT—VAL PORT—VAL EQU 3(五 ) 其它 (伪指令部分 ) 除上述寄存器 ,变量 ,标记 , 数外都是伪指令 segement/ENDS

Page 104: 第一章  概述 第一节  引言

113

三、表达式 表达式是由标记、符号通过运算符组合起来的序列。 一个表达式是一个由操作数和运算符组合的序列。 ( 一 ) 操作数 r , m , im(立即数 ) 1. 常量操作数 (-2 -1 , 2 -1), 即 (-65535 , +65535) 2.存储器操作数 两种:标号——指令语句符号地址 如 JMP, Call 变量—— 4 种寻址方式 --直接 -- 基址 --变址 -- 基址加变址 可存放在 M 中的值 三种属性 -- 段值 -- 段内偏移量 --类型 ( 二 ) 运算符

16 16

Page 105: 第一章  概述 第一节  引言

114

有以下五种:算术运算符 逻辑运算符 关系运算符 分析运算符 合成运算符 1. 算术运算符 mod 当算术运算符用于存储器时 , 只有当结果有明确的、有意义 的物理解释时才有效。 如 SUM+2 地址加 2, 而不是内容加 2 CYCLE-5 NOT_DONE-GO 同段 而 SUM-CYCLE 前者是数据段 , 后者是码段 在不同段 , 相减无意义 2. 逻辑运算符 按位操作的 AND 、 OR 、OR 、 NOT 。 其操作数只能是数字的 , 且结果是数字 , 存储器操作数不能进

Page 106: 第一章  概述 第一节  引言

115

行逻辑运算。 如 NOT 1111 1111=0000 0000 又如 1111 0000 1111 0000 OR SUM 无效的 IN AL,PORT-VAL OUT PORT-VAL AND OFEH,AL 若 PORT 是 -VAL 是偶数 , “ 与”后仍是同一端口 若 PORT-VAL 是奇数 , “ 与”后是 PORT-VAL 低的下一个端口作为汇编的运算符是在程序汇编时计算 , 而作为指令的助记符 , 则在程序执行时计算的 . 如 AND DX , PORT-VAL AND OFEH 程序执行时计算3.关系运算符 相等 EQ 不等 NE 小于 LT 大于 GT 小于等于 LE 大于等于 GE 关系运算的两个操作数或者都是数字 , 或者都是同段存储器地址 ,

汇 编 时 计 算

Page 107: 第一章  概述 第一节  引言

116

结果是数值。 0——关系假 , 0FFFFH——关系真。 如 mov BX , PORT-VAL LT 5 若 PORT-VAL 的值 <5 , 关系为真 , 则汇编程序在汇编程序后产生的语句为 mov BX , OFFFFH 否则 mov BX , 0 一般把关系运算符与逻辑运算组合使用。 又如 mov BX , ((PORT-VAL LT 5) AND 20) OR((PORT-VAL GE 5) AND 30) 若 PORT-VAL 的值 <5 汇编程序为

mov BX , 20 否则 mov BX , 30

Page 108: 第一章  概述 第一节  引言

117

第三节 指示性语句 ——伪指令

Page 109: 第一章  概述 第一节  引言

118

一、符号定义语句 ( 一 )等值语句 EQU 定义一个值、别的符号名、可执行指令 格式 NAME EQU Expression 如 buffer-size EQU 32 count EQU CX 定义为寄存器 CX 的同义语 CBD EQU ADD 定义为加法 New-port equ port-VAL 在解除 EQU 以前 , 不能重新定义。 ( 二 )等号语句 EMP 能对符号进行再定义 emp=6 , emp=7 , emp=emp+1 ( 三 )解除语句 PURGE 用于已经用的 EQU 语句的情况下 格式 Purge 符号 1 , 符号 2 , … , 符号 n 用 purge解除后的符号可以再定义。 如 purge NEW-PORT NEW-PORT EQU PORT-VAL+2二、数据定义语句

Page 110: 第一章  概述 第一节  引言

119

为一个数据项分配存储单元 , 且并赋符号名和初值。 如 THING DB ? ; 定义一个字节 BIGGER-THING DW ? ; 定义一个字 BIGGEST-THING DD ? ; 定义一个双字

THING DB 25 ; 一个字节把 25放入和 BIGGER-THING DW 4142H; 与 THING 相联系的 存储单元 同样 biggest-thing DD 12345678H

当汇编程序汇编时遇到“?” , 则它仍然为数据项分配相应存 储单元 , 以便存放指令执行的中间结果 ,并不产生一个目标码 来初始化存储单元。

78563412

biggest-thing+1+1+1

Page 111: 第一章  概述 第一节  引言

120

如 POWERS-2 DB 1 , 2 , 4 , 8 , 16

ALL-ZERO DB 6 DUP(0) DB 100 DUP(0) DB 100 DUP(0) 又如 ALPHA DW 2 DUP(3 DUP((1,2 DUP(4,8),6),0)

POWERS-2 1248

16

5 个

148486

148486

148486

Page 112: 第一章  概述 第一节  引言

121

字符串 ( 每个字符用 ASCII 表示 , 为一个字节 ) 如 EXAM1 DB ‘THIS IS AN EXAMPLE’ 或者 DB ‘ T , H , I , S ’ 字符串的定义必须是 DB 命令

一个存储单元的类型: 1. 数据字节

SUB DB ? ; 定义一个字节 2. 数据字 BIGGER DW ? ; 定义一个字 3. 数据双字 BIGGEST DD ? ; 4.NEAR 指令单元 5. FAR 指令单元 一个指令单元能出现在 JMP 或 CALL 语句中。 若类型是 near, 产生一个段内 JMP 、 CALL,2 个字节。 若类型是 far , 产生一个段间 JMP 、 CALL,4 个字节。 分析运算符把存储器地址分为 5 个:

Page 113: 第一章  概述 第一节  引言

122

seg

offset type size length 指令所在段的段地址加偏移量 一个存储单元地址加或减形成的新的存储单元与原来的存储 单元有相同的类型。 seg 功能 : 可用 seg返回变量或标号所在段的段基址。 如 mov AX, seg ABC 把变量 ABC 的段地址 AX offset 功能 :offset 可返回变量或标号的所在段的偏移量。 type 功能 :返回一个表示变量或标号类型的数值。 变量 标号 DB 1 NEAR -1 DW 2 DD 4 FAR -2

Page 114: 第一章  概述 第一节  引言

123

如 ALFA DW 20 DUP(?)

mov AL , type ALFA ; (2AL) Length 分配单元长度操作符 功能:返回给该变量的单元数 仅对 DUP项返回变量单元数 , 对其它情况均返回值 1 。

如 ALFA DW 20 DUP(?) BATA DB 12 mov AL, Length ALFA; (20 AL) mov AH, Length BATA; (1 AH) size 功能 :返回分配给该变量的字节单元数。 如 mov AL , size ALFA ; (40 AL) mov AH , size BATA ; (1 AH) 显然 size ALFA=(Length ALFA)*(type ALFA) 合成运算符 (PTR 、 THIS) type PTR variableconstant expression

Page 115: 第一章  概述 第一节  引言

124

在 PTR 左边的操作数有 3 种: byte , word , Dword 。 在 PTR 右边的操作数生成与原存储器操作数段地址、段内偏 移量相同 , 类型不同的新的存储器操作数。 如 OPER1 DB 1 , 2 OPER2 DW 1234H , 5678H

mov AX , OPER1+1 mov BL , OPER2

请考虑一下指令中的斜体部分是否表示正确正确的应该改为 mov AX , WORD PTR OPER1+1 mov BL , BYTE PTR OPER2

对于 mov AX , WORD PTR OPER1+1 OPER1+1 的内容 AX , 即 OPER1+1 的内容 AL 02 AL 所以 (AX)=3402H

Page 116: 第一章  概述 第一节  引言

125

而对于 mov AL , BYTE PTR OPER2 把 OPER2 的第一个字节的内容 BL , (AL)=34H THIS 与 PTR类似 其段地址加上段内偏移量就是汇编时当前值 段地址 + 段内偏移量

WBUFFER1 EQU THIS WORD BUFFER2 EQU THIS BYTE DWBUFFER3 EQU THIS DWORD三、段定义语句 它的主要命令有 4 个: segment ENDS assume 定义 CS 、 ES 是什么段 org 规定段内的起始地址 下面我们来看一个例子: my_DATA segment x DB?

Page 117: 第一章  概述 第一节  引言

126

y DW? z DD? My_DATA ENDS

my_EXTRA segment ALPHA DB? BETA DW? GAMMA DD? my_EXTRA ENDS

my_stack segment DW 100 DUP(?) TOP EQU THIS WORD my_stack ENDS

my_CODE segment assume CS:my_CODE , DS:my_DATA

ES:my_EXTRA , SS:my_stack

Page 118: 第一章  概述 第一节  引言

127

start : mov AX , seg x mov DS , AX mov AX , seg ALPHA mov ES , AX mov AX , my_stack mov SS , AX mov SP , offset TOP

my_CODE ENDS END start 在汇编语言的源程序中 , 定义 CS 、 SS 、 DS 、 ES 每一个段必须 有一个名字。一个段由命令 segment 开始 , ENDS 结束 , 成对出现。 最后用 END 结束源程序。四、过程定义语句 在 8088 中调用过程和返回的指令是 call 和 ret过程定义语句。 PROC 和 ENDP 是在说明 call 和 ret 是 NEAR还是 FAR型。 如 procedure_name proc [NEAR]

Page 119: 第一章  概述 第一节  引言

128

. ret

procedure_name ENDP 谨记 proc 和 ENDP 成对出现。 一个过程定义的例子: my_code segment my_code ENDS up_count proc near END ADD CX,1 RET up_count ENDP start : call up_count

call up_count

Page 120: 第一章  概述 第一节  引言

129

五、结束语句 segment—ENDS proc—ENDP END END < 表达式 > 表达式为第一条要执行的指令的地址

Page 121: 第一章  概述 第一节  引言

130

第四节 指令语句

Page 122: 第一章  概述 第一节  引言

131

指令助记符 指令前缀 操作数寻址方式 串操作指令一、指令助记符 ( 一 )NOP:保留一些单元为以后填入指令时用 ,放慢速度。 (AX 自行交换 ) ( 二 )NIL:保留空格 如 CYCLE : NIL CYCLE : INC AX INC AX二、指令前缀 1. 段超越:由 assume 语句的信息选择段寄存器。 如 mov BX , ES :SUM

由汇编程序决定在用选择的 段寄存器是否超越 2. 重复: rep repE 当相等时重复 repNE 当不相等时重复

指令语句

Page 123: 第一章  概述 第一节  引言

132

repZ Z=1 时重复 repNZ Z=0 时重复 3.锁定: LOCK三、操作数寻址方式 共有 8 种: 立即 寄存器 直接 基址 变址 基址变址 基址或变址 + 位移量 基址变址 + 位移量

如 SUM DB ? 字节 INC SUM 一个字节增量 如 mov AL , [BX] 字节 由目的指定 [BX]也是字节型 而 INC [BX] 是错误的 INC BYTE PTR [BX] 一个字节增量 INC WORD PTR [BX] 一个字增量四、串操作指令

Page 124: 第一章  概述 第一节  引言

133

请回忆一下之前学过的指令 。

COMPS (SI) -(DI) 指令语句

指示性语句:符号定义、分存储单元、分段 码段 栈段 数据段 如两个未压缩的 BCD 码相加。 先数据段、再堆栈段、码段 DATA segment stri1 DB ‘1’ , ‘7’ , ‘5’ , ‘2’ stri2 DB ‘3’ , ‘8’ , ‘1’ , ‘4’ count equ $-stri2 $ 表示当前地址计数的值

源程序

程序

MOVS (DI) (SI) DI1,2 SI 1,2 SCAS AL/AX-(DI) DI1,2 SI 1,2 LODS AL/AX(SI) SI 1,2STOS AL/AX(DI) DI 1,2

关于 $

Page 125: 第一章  概述 第一节  引言

135

DATA ENDS stack segment stack para stack ‘stack’ stapN DB 100 DUP(?) TOP EQU Length stapN stack ENDS CODE segment assume CS:code , SS:stack , DS:DATA , ES:DATA start proc FAR PUSH DS mov AX , 0 PUSH AX go: mov AX , DATA mov DS , AX mov ES , AX mov AX , stack mov SS , AX mov AX , TOP mov SP , AX

在堆栈中推入一个段地址 DS 和 IP 返回 DOS

Page 126: 第一章  概述 第一节  引言

136

CLC CLD mov SI , offset stri1 mov DI , offset stri2 mov CX , count cycle: LODS stri1 ADC AL , [DI] AAA STOS stri2 LOOP cycle RETSTART ENDPCODE ENDS END start 定义数据 , 堆栈段 , 代码段 , 过程定义语句。 RET返回 DS , IP(0000H) DOS 源——目标——连接——程序前缀

Page 127: 第一章  概述 第一节  引言

137

第五节 汇编语言程序设计及举例

Page 128: 第一章  概述 第一节  引言

138

一、概述 1. 汇编语言源程序的结构 NAME 数据段名 segment 变量定义 数据空间预量 数据段名 ENDS 堆栈段名 segment para stack ‘stack’ 堆栈空间预量 堆栈段名 ENDS 代码段名 segment assume 段寄存器地址说明 start : 段地址装填 主程序 过程名 1 proc类型 过程体 过程名 1 ENDP

Page 129: 第一章  概述 第一节  引言

139

过程名 N proc类型 过程体 N 过程名 N ENDP 代码段名 ENDS END start2. 段寄存器的装填 CS 由系统在加载程序后由系统自动装填 SS也可以由系统自动装填 , 但必须将参数写全 如 stack 、 segment 、 para 、 stack 、‘ stack’ 当程序装入内存时 , 系 统把堆段地址和栈指针置入 SS 和 SP , 因而不必在代码段装填 SS 和 SP 。 DS 、 SS 、 ES 的装填 mov AX , 数据段名 mov DS , AX3.返回 DOS DOS 下运行汇编程序 , 当程序执行结束后返回 DOS 。 过程名 proc far push DS

Page 130: 第一章  概述 第一节  引言

140

mov AX , 0 push AX

ret 过程名 ENDP ENDP 过程名 (INT 20H) 是返回 DOS 的系统调用 , 系统将执行 INT 20H 系统 (装入程序时 )放在程序段前缀的头二个字节 (100H 字节的信息区 , 放在程序段前 ) 当执行程序后 , DS 和偏移量 CS 、 IP, 从而执行 INT 20H4. 编写程序步骤 (1)建立数学模型

(2)确定解决模型的算法 (3)画流程图 工作框 : 一个入口 , 一个出口 判断框 : 一个入口 ,几个出口

Page 131: 第一章  概述 第一节  引言

141

子程序框: 一个入口一个出口

程序走向:

(4) 分配内存单元和寄存器 (5) 写程序二、直线运行程序 两个 32 位无符号数乘法 A B

C D

ADBC

BD

AC+最后乘积

16 位

Page 132: 第一章  概述 第一节  引言

142

name data segmentmulnum dw 0000 , ffff , 0000 , ffff , 4 dup(?) data ends stack segment para stack ‘stack’

db 100 dup(?) stack ends code segment assume cs:code , ds:data , ss:stack , es:data start proc far being: push ds ; mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax lea bx , mulnummulu32: mov ax , [bx] ; BAX

DS 中包含的是程序段前的起始地址 设置返回至 DOS 的段值和 IP 值

置段寄存器初值

Page 133: 第一章  概述 第一节  引言

143

mov si , [bx+4] ; D SI mov di , [bx+6] ; C DI mul si BD (DX , AX) mov [bx+8] , ax mov [bx+a] , dx mov ax , [bx+2] A AX mul si ; AD(DX , AX) 乘积 2 add ax , [bx+a] adc dx , 0 mov [bx+a] , ax mov [bx+c] , dx mov ax , [bx] B AX mul di B C(DX , AX) 乘积 3 add ax , [bx+a] 与乘积 3 的相应部分积相加 adc dx , [bx+c] mov [bx+a] , ax mov [bx+c] , dx pushF 保存 C(保存后一次相加的进位 )

保存乘积 1

乘积 2 与乘积 1 的相应部分相加

乘积 3 与乘积 2 的相应部分相加

Page 134: 第一章  概述 第一节  引言

144

mov ax , [bx+2] AAX mul di AC(DX , AX) 乘积 4 popF adc ax , [bx+c] 与乘积 4 相应部分相加 adc dx , 0 mov [bx+c] , ax mov [bx+e] , dx ret start endP code ends end begin

P127 例 : 32 位有符号数乘法 name data segment

sign db ?mulnum dw X1 , X2 , X3 , X4 , 4 dup(?) data ends

Page 135: 第一章  概述 第一节  引言

145

stack segment para stack ‘stack’ db 100 dup(?)code segment assume cs:code , ds:data , ss:stack , es:datastart proc farbegin:push ds mov ax , 0 push ax mov ax , data mov ds , ax mov sign , 0 置符号初值 lea bx , mulum mov ax , [bx] B AX mov dx , [bx+2] A DX mov si , [bx+4] D SI mov di , [bx+6] C DI cmp dx , 0 检验正、负 jns other 若为正 ( 即 S=0)转至 other

返回至 DOS

Page 136: 第一章  概述 第一节  引言

146

not ax not dx add ax , 1 adc dx , 0 not sign 改变符号 mov [bx] , ax mov [bx+2] , dxother: cmp di , 0 检验乘数符号 jns go mul 若 S=0 则转移到 go mul not si not di add si , 1 adc di , 0 not signgo mul: call mulu32 调用无符号乘数 cmp sign , 0 检验S 位 je done Z=1( 相等 ) 乘积为正 , 结束 not word ptr [bx+8]

若为负则求补

保存被乘数

乘数求补

Page 137: 第一章  概述 第一节  引言

147

not word ptr [bx+a] not word ptr [bx+c] not word ptr [bx+e] add word ptr [bx+8] , 1 adc word ptr [bx+a] , 0 adc word ptr [bx+c] , 0

adc word ptr [bx+e] , 0 done: ret start endP mulu32

三、分支程序设计

( P129 )

乘数求补

1 X>0 y= 0 X=0 -1 X<0

y-1 y0 y1

x>0<0

=0

出口

Page 138: 第一章  概述 第一节  引言

148

sigef mov AX , buffer OR AX , AX 执行一个判断 JE ZERO Z=1 转移至 zero JNS plusS=0 转移至 plus mov BX , FFFFH y-1 JMP conti zero : mov BX , 0 JMP conti plus : mov BX , 1 conti :例:数据 AL 的被置位的情况控制转移到 8 个子程序中。 AL : 0000 0001

0000 0010 0000 0100 0000 1000

0001 0000 0010 0000 0100 0000 1000 0000

R1R2R3R4R5R6R7R8

Page 139: 第一章  概述 第一节  引言

149

name data segment brtab dw R11 子程序 R1 入口地址的 IP 值 dw R12 子程序 R1 入口地址的码段值 dw R21 同上 dw R22 同上

dw R81 dw R82 data ENDSstack segment para stack ‘stack’ DB 100 DUP(?)TOP equ $-STACKstack endscode segmentstart proc far assume cs:code , ds:data , ss:stack , es:data begin : push DS

启动

D0=1 ?

D1=1 ?Y

Y

Y

N

N

R1

R7

R2

R8

Page 140: 第一章  概述 第一节  引言

150

mov AX , 0 push AX mov AX , data mov DS , AX mov AX , stack mov SS , AX mov AX , TOP mov SP , AX lea BX , brtab 设跳转地址的地址指针gtbit: RCR AL , 1 JC getad C=1 时转移 INC BX INC BX INC BX INC BX JMP gtbitgetad:JMP Dword ptr [BX] ; 段间间接转移 start ENDP

C

BXBX+4

Page 141: 第一章  概述 第一节  引言

151

四、循环程序设计

例 1. 用计数器控制循环 寻找一串给定个数的数中的最大值 ,并放入指定单元中。 每个数用 16 位表示。 name data segment buffer dw X1 , X2,…, Xn count equ $-buffer max dw ? data ends stack segment para stack ‘stack’

工作部分 控制部分

循环体

结构 循环结束条件

循环初态 循环工作初态:如标志位、寄存器清零 结束条件初态: CX 的初态

Page 142: 第一章  概述 第一节  引言

152

DB 64 (?) top equ $-stackstack endscode segment assume cs:code , ds:data , ss:stack , es:databegin : push DS mov AX , 0 push AX mov AX , data mov DS , AX mov AX , stack mov SS , AX mov AX , top mov SP , AX mov CX , count SHR CX , 1 lea bx , buffer mov AX , [BX]

Page 143: 第一章  概述 第一节  引言

153

INC BX INC BX dec cxagain: cmp AX, [BX]

JGE next mov AX , [BX]next: INC BX INC BXLOOP againstart endPcode ENDS END start

例 2. 条件控制循环 求 16 位无符号数的整数平方根    X2=(N/X1X1)/2 X1=(N/200+2) 若 X1 是数 N 的平方根的近似值 , 则 X2 是数N的平方根的最近   似值 , 这个称为逐次逼近法

Page 144: 第一章  概述 第一节  引言

154

name data segment num dw 2710H result dw ? digit equ 200 data ends stack segment para stack ‘stack’ db 100 dup (?) stack endscode segment assume cs:code , ds:data , ss:stack , es:databegin: mov ax , data mov ds , ax mov ex , ax lea bx , num mov ax , [bx] axN mov si , ax SIN

Page 145: 第一章  概述 第一节  引言

155

mov di , digit DI200 cwd       双字扩展 AX(DX , AX) div di N/200 add ax , 2 N/200+2 AX=X1conti: mov cx , ax mov ax , si cwd div cx add ax , cx shr ax , 1 mov dx , ax sub dx , cx je done cmp dx , 1 jne contidone:mov [bx+2] , ax retstart endP

Q

Page 146: 第一章  概述 第一节  引言

156

code ends end begin3. 多重循环 delay : mov DX , 3FFH time : mov AX , FFFFH time1 : dec AX NOP JNE time1 dec DX JNE time     ret ————延时程序4. 用开关量控制循环

        name data segment buffer dw 05…05 , 05…05 block dw 12 dup(?)

第一循环支路 第二循环支路

Page 147: 第一章  概述 第一节  引言

157

count1 equ 5 count2 equ 7

mov dx , 0 mov cx , count1+1    6CX lea bx , buffer lea si , blockagain : mov ax , [bx] cmp dx , 0        开关量是否为零 jne another 不为零则转移到another call fun1 为 0 loop next mov dx , 1 mov cx , count2+1 8CX jmp again next : mov [SI] , ax inc bx inc bx

Page 148: 第一章  概述 第一节  引言

158

inc SI inc SI jmp againanother : call fun2 loop next ret start endP

fun1 proc add ax , ax ret fun1 endP fun2 proc add ax , ax add ax , ax ret fun2 endPcode ends end begin

Page 149: 第一章  概述 第一节  引言

159

5. 逻辑尺    

Page 150: 第一章  概述 第一节  引言

160

五、字符串处理程序设计  常用的字符编码是 ASCII 码字符。   09 为 ASCII 码的 30 H39H AZ 为 ASCII 码的 41H5AH 常用的控制字符 ( 不同系统有不同控制字符 )

   0AH 换行  LF 0DH 回车  CR     字符串的长度常以某个特殊字符作为结束标志 , 如 $ 、 CR 。

 例 从头搜索字符串的结束标志 , 统计字符个数。 (P141) name length-of-string data segment string db ‘abcduvwxyz’ , 0dH LL db ? Cr equ 0dH data endS stack segment para stack ‘stack’

stack endS code segment

Page 151: 第一章  概述 第一节  引言

161

assume cs:code , ds:data , es:data , ss:stack start proc far begin: push ds mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax lea di , string ;    设串的地址指针 mov dL , 0 置串长度初值= 0 mov AL , cr      串结束标志 AL again: scasb         搜索串 je done inc DL jmp again done: lea bx , LL mov [bx] , dL ret

Page 152: 第一章  概述 第一节  引言

162

  start endP code endS end begin 为避免出现 cr 丢失 , 进入死循环 ,设循环次数 > 字符串长度   data segment string db ‘abcdefghij’ , odh count equ $-string LI db ? data ENDS stack segment para stack ‘stack’ db 100 dup(?) stack ends code segment assume cs:code , ds:data , es:data , ss:stack    start proc far begin: push ds mov ax , 0

push AX 返回 DOS

Page 153: 第一章  概述 第一节  引言

163

mov ax , data mov ds , ax mov ES , ax lea di , string mov dL , 0     串长度初值为零 mov aL , 0dh mov cx , count+10  置循环次数 >串长度again: scasb je done inc dL

dec cx jne again jmp error  由计数停止循环 , 则出错 , 转至出错处理程序

done: mov LL,dL retstart endPcode ends end begin

给段寄存器赋初值

Page 154: 第一章  概述 第一节  引言

164

( 二 )找串中的第一个非空格字符  P142 例 从一个给定的字符串中 , 从头开始 ,找到第一个非空格      字符。    name data segment string db ‘abcdefghij’ , ‘$’ count equ $-string string2 db count dup(?) string3 db 0dh , 0ah , ‘$’ data ends stack segment para stack ‘stack’

db 100 dup(?) stack ends code segment assume cs:code , ds:data , es:data , ss:stackstart proc farbegin: push ds mov ax , 0

Page 155: 第一章  概述 第一节  引言

165

push ax mov ax , data mov ds , ax mov es , ax lea di ,string mov cx , count mov Al ,20H repe scasb

inc cx

mov bx, count

sub bx, cx

lea di, string2

lea si, string

add si, bx

rep movsb

关于rep

Page 156: 第一章  概述 第一节  引言

169

lea dx , string

mov ah , 9int 21H

lea dx , string3mov ah , 9int 21Hlea dx , string2mov ah , 9int 21H retstart endPcode ends end begin

注: ah=9 的功能是显示字符串 , 要求被显示输出的字符必须以 $字 符作为定界符 , 以 $ 为标记计算串的长度。

显示串 2

显示串 1

显示串 3

Page 157: 第一章  概述 第一节  引言

170

( 三 ) 用空格代替前导零

  namedatastring1 db ‘0000abcderty876’ , ‘$’count equ $-string1-1string2 db count dup(?) , ‘$’string3 db 0dh , 0ah , ‘$’data endsstack db 100 dup(?)stack endscode

lea di , string1mov cx , countmov aL , ‘0’repe scasb

Page 158: 第一章  概述 第一节  引言

171

inc cx mov bx , count sub bx , cx lea di , string2 push cx mov cx , bx mov aL , 20h rep stosb pop cx lea si , string1 add si , bx rep movsb lea dx , string1 mov ah , 9 int 21h lea dx , string3 mov ah , 9 int 21h

        用空格填满串2

     显示串1

        显示回车、换行

Page 159: 第一章  概述 第一节  引言

172

lea dx , string2 mov ah , 9 int 21h start code End begin( 四 ) 加偶校验到 ASCII 字符  若有一个 ASCII 字符串 ,放在单元 string 内 , 要求从串中取出每  一个字符 ,检查其中包含“ 1” 的个数 , 若已为偶数 , 则它的最高有  效位置“0” ,否则最高有效位置“ 1” 。  name data string db ‘1234567890’ count equ $-string data ends stack db 100 dup(?) stack code begin:push ds

     显示串 2

Page 160: 第一章  概述 第一节  引言

173

mov AX , 0 push AX lea si , string mov cx , countagain : lodsb and al , al jpe next or aL , 80h  AL 最高低置1 mov [si-1] , aLnext : dec cx jnz again ret

Page 161: 第一章  概述 第一节  引言

174

六、码转换程序设计 硬件 查表 软件 ( 一 )16 进制 ASCII  若一个二进制数码串 , 把每一个字节中的二进制转换成2位  16 进制数的 ASCII 码 , 高 4 位 ASCII 码放在地址高的单元。

六、码转换程序设计 硬件 查表 软件 ( 一 )16 进制 ASCII  若一个二进制数码串 , 把每一个字节中的二进制转换成2位  16 进制数的 ASCII 码 , 高 4 位 ASCII 码放在地址高的单元。

4 位 2 进制 0~15, 可用 1 位 16 进制 (0 ~ 9,A~F)ASCII 码 ,0 ~9 的 ASCII 码只要将 16 进制数加上 30H 、 A ~F 的 ASCII 码加上 37H 就可得到对应的 ASCII 码。 根据是否大于 10 来判断是加 30H 还是加 37H ,完成 16 进制(2 进 制 ) 向 ASCII 码的转换。 name data L1 dw 2 string db 34h , 98h L2 dw ? buffer db 2×2 dup(?)

Page 162: 第一章  概述 第一节  引言

175

data ends stack seg para stack’41-A’ db 100 dup (?) stack ends mov cx , L1 lea bx , string lea si , buffer mov ax , cx sal cx , 1 mov L2 , cx mov cx , axagain : mov AL , [bx] mov dL , aL and AL , 0FH call change mov aL , DL push cx mov cL , 4 shr aL , cl pop cx

高 4 位 右移 4 位

Page 163: 第一章  概述 第一节  引言

176

call change inc bx loop again ret start endP change proc cmp aL , 10 jL add-0 add AL , ‘a’-‘0’-10 add-0 : add aL , ‘0’ (AL+30H)AL<10 mov [si] , al (AL+37H) AL>10 inc si ret change endP code ends end begin

Page 164: 第一章  概述 第一节  引言

177

( 二 )ASCII 码到十进制 (BCD) 的转换 若有一输入的 ASCII, 要把其中的数码 ( ‘0’~‘9’之间 ) 取出来 ,转 换为未组合的 BCD 码 ,存放另一区 ,并统计串长度 ,放入此区的第 一个字节。 502D 0101, 0000,0010 未组合 BCD 0101 0000, 0010 数字的 ASCII 码是一种未组合 BCD name data L1 db 10 string db ‘123asdfgki’ buffer db ? db 10 dup(?) stack db 100 dup (?) stack ends code

Page 165: 第一章  概述 第一节  引言

178

assume start proc farbegin : push ds mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax mov CL , L1 mov CH , 0 lea si , string 一区 lea di , buffer 另一区 inc di 目的是首地址放 DL的值 mov dL , 0 数码计数器置 0

again : lodsb cmp aL , ‘0’ jL next cmp aL , ‘9’

返回 DOS

段寄存器赋值

Page 166: 第一章  概述 第一节  引言

179

jg next and aL , 0fh stosb inc dLnext : loop again mov buffer , dL ret start code End begin

Page 167: 第一章  概述 第一节  引言

180

( 三 ) 把 BCD 码转换为二进制 若有一个 16 位存储单元 ,存放 4 位 BCD 数 , 要把它转换成二

进制 ,并 放在另一存储单元中。( (千位数 ×10+百位数 ) ×10+ 十位数 ) ×10+ 个位数参见流程图参见流程图data

dnum dw 9999h bnum dw ? data mov ax , dnum mov di , ax mov dx , ax mov bx , ax and bx , 000fh and dx , 00f0h mov cL , 4 shr dx , cL

and di , 0f00h mov cL , 8 shr di , cL and ax , f000h mov cL , 12 shr ax , cL

add ax , ax mov cx , ax add ax , ax add ax , ax add ax , cx add ax , di

Page 168: 第一章  概述 第一节  引言

183

( 四 ) 二进制到 BCD 转换 关键 :找出二进制包含 1000,1000,100,10 的个数 , 这样即可将二进 制转换为相应的 BCD 码。 例:有一个 16 位二进制数要转换为相应的十进制数 ASCII 码。

   Tips : Tips : 数字的数字的 ASCIIASCII 码是一种非压缩的码是一种非压缩的 BCDBCD 码。码。   参见其流程图参见其流程图 bnum dw 270FH strg db 5 dup(?)

mov ax , bnum lea bx , strg mov dL , 0again1 : sub ax , 2710H ; AX-10000 js next1 inc dL jmp again1

next1 : add ax , 2710H add dl , 30H mov [bx] , dL inc bx mov dL , 0again2 : sub ax , 03e8H

next2 : add ax , 03e8H

Page 169: 第一章  概述 第一节  引言

185

(五 ) 从二进制到 ASCII 码串的转换 若要把1个二进制位串显示 , 要把串中每一位转换为它的 ASCII 码。 例: 16 位二进制数 , 每一位转换为相应 ASCII存入 string 。

   num dw 4f78h string db 16 dup(?) lea di , string mvo cx , length string push di push cx mov aL , 30h rep stosb pop cx pop di mov aL ,31H mov bx , numagain : rcl bx , 1

Page 170: 第一章  概述 第一节  引言

186

jnc next mov [di] , aL next : inc di loop again ret

七、列和表的程序设计  列-由数据单元组成 ; 表-特殊目的数据结构。  有关列和表的主要操作:  查找、增加、删除、对其进行分类或排序。   ( 一 )无序列    加一个项至一个无序列 ,判断列中有无    若无 , 则把它加在列的最后。    参见其流程图参见其流程图

Page 171: 第一章  概述 第一节  引言

187

name data seg buffer db 10, ‘abcdefghij’ db ? key db ‘$’ data ends stack seg para stack ‘stack’ code segment assume:cs:code,ds:data, es:data,ss:stack start pro far begin: push ds mov ax,0 push ax mov ax,data mov ds,ax

mov es,ax lea di,buffer mov ax,data mov ch,0 mov cl,[di] 列长度→ cx

inc di mov al key repnz scasb je done move [di],al inc buffer done ret start endp code ends end begin

Page 172: 第一章  概述 第一节  引言

188

2. 删去一个元素—找到要删去的元素,列长度 -1,元素上移 buffer db 10, ‘abcdefghij’ key db ‘f’ …… lea di,buffer mov ch,0 mov cl,[di] 串长度→ cx inc di 指向第一元素 mov al,key repnz scasb jne done 未找到,结束 dec buffer 若找到,串长度 -1 mov si,di ‘f’的下一个地址→ si

dec si si-1→si, 原来‘ f’ 的地址 xchg si, di rep movsb (di)←(si)

done: ret

start endp

code ends

end begin

Page 173: 第一章  概述 第一节  引言

189

P156/例 3-21.找出元素序列的最小值和最大值

取列长度→ cx

取列中第 1元素

送 min

送 max

取下一元素

al=min

N

al>min

1

Y

N

2

3

2

al<max

Nal→max

1

Y

al→min

3 Y

修改地址

完成否

Y

4

4

Page 174: 第一章  概述 第一节  引言

190

buffer db10,22,-12,80,-6,-70,

-9,127,-10,00,40

minval db ?

maxval db ?

lea bx, buffer

mov ch,0

mov cl, [bx] inc bx bx 指向列中第一个元素 dec cx

mov al, [bx]

mov minval, al

mov maxval, al

inc bx

dec cx

again: mov al, [bx] cmp al, minval je next 相等→ next jg a1 若到元素大 ,

转 a1 mov minval,al al< 现在

值 →minv

al jmp next

a1:cmp al, maxval jl next mov maxval,al next:inc bx dec cx jne again ret

Page 175: 第一章  概述 第一节  引言

192

( 二 )气泡分类法   如下的 10 个数 :22 、- 12 、 80 、- 6 、- 70 、- 9 、 127 、           - 10 、 00 、 40 。   如果按数的大小排列:

    两者的比较办法:第 N 个数 e 与第 N- 1 个数 e  相比较 , 若 e > e   , 则不变换;若 e <e   , 则变换。 e N –1>e N-2

e2>e1

若数组长度为 N ,最多经过 N-1趟,可使数组大小排列有序。 当第一趟比较结束,数组中的最小值冒到了顶部,为了除 去不必要比较,每次开始置标志为 0( 若交换 -1 ;若不交换 0) 下次比较若为 -1 ,就说明尚未排好;若为 0 ,说明排好,便 停止循环。

Page 176: 第一章  概述 第一节  引言

193

   如果按数的大小排列:    两者的比较办法:第 N 个数 e 与第 N- 1 个数 e  相比较 , 若 e > e   , 则不变换;若 e <e   , 则变换。 e N –1>e N-2

e2>e1

若数组长度为 N ,最多经过 N-1趟,可使数组大小排列有序。

当第一趟比较结束,数组中的最小值冒到了顶部,为了除 去不必要比较,每次开始置标志为 0( 若交换 -1 ;若不交换 0) 下次比较若为 -1 ,就说明尚未排好;若为 0 ,说明排好,便 停止循环。 参见流程图参见流程图 程序如下:

buffer dw 22 , -12 , 80 , -6 , -70 , -9 , 127 , -10 , 00 , 40 count equ $-buffer conti : mow bL , 0 mov cx , count

N N -1N

N -1 N -1N

Page 177: 第一章  概述 第一节  引言

194

初始化

交换标志为 0

取数组长度为 N

设变址值

取 ej

交换

标志为 -1

修改变址值

比较完

变换标志=0 ?

返回

N

Y

YN

Yej>e j-1

Page 178: 第一章  概述 第一节  引言

195

mov si , cx dec si dec si shr cx , 1again : mov ax , buffer [si] cmp ax , buffer [si-2] jge next xchg ax , buffer [si-2] mov [si] , ax mov bL , -1 next : dec si dec si loop again cmp bL , 0 jne conti ret

Page 179: 第一章  概述 第一节  引言

196

简化之: 第二趟 e2,e1比较多余 大循环 (趟 )I=2 ,每趟后 I+1I 小循环 (次 ) 每一趟中的小循环变量为 N( 数组长度 ) 每两两比较一次 N 减量, N-1N 当 N<I ,停止小循环。 若到某一趟,只发生 eN,e N-1交换,或无交换 无需要比较,前 N-2 个元素已经有序,整个 e

N,e N-1交 换后,数组有序了。 若标志 =N( 每趟小循环的初值不变,则停止排序 )

Page 180: 第一章  概述 第一节  引言

197

(三 ).有序列操作 :p160 string dw 10,-80,-50, 00, 20,30,

40,100,2000,10000,

25000

key dw 2000

sflag dw ?

lea di, string mov cx, [di] 列的长度→ cx inc di

inc di

mov ax, key

cmp ax, [di] jl none 若 <第一元素 ,列中无关键字

mov bx, cx sal bx, 1 bx←有序列的元素 cmp ax, string [bx] 与最后一个 元素比较 jg none 无字 repne scasw 否则搜索 jne none 未找到 , 结束 dec di 若找到 ,DL 指向关键字 dec di mov sglag di jmp done none:mov ax, -1 mov sflag, ax 未找到 , -1→sflag

done: ret

Page 181: 第一章  概述 第一节  引言

198

( 四 ). 连接队列 列中每一项除了数据元素外 ,还包括指向下一列元素

的地址指针 ,占有内存空间 ,不用重新排列 .

( 五 ). 表 P166 例 .有一个 0度— 90度的三角函数表 ,给定一个角

度值 , 查出相应的正弦函数值 .

指向列的开始 →

指向元素 2元素 1的数据

元素 1

→指向元素 3元素 2的数据

元素 2

→最后元素元素 3的数据

元素 3

602060006020

→ 6060

第 1个元素6060

→ 60A0

第 2个元素 60A0

→ 0000

最后元素

60606000 60206060 60A0

60A0

→ 0000

Page 182: 第一章  概述 第一节  引言

199

符号 sign=0

取角

角〈 181

sign=1

角 =角 -180度

N

Y

角〈 91度

角 =180度 - 角

1

1

查表得到正弦值

符号作为最高有效值

ret

Page 183: 第一章  概述 第一节  引言

200

sintab db 0,2,4,6,8,0AH rest db ?

mov al, 5 xon dl, dl 置 0,符号为正 cmp dl, 180 jb simpos c=1, 小于为正 or dl, 80 否则符号置为负 sub al, 180 sinpos:cmp al, 91 js getsin neg al 角度取补, -al→al

add al, 180 变为 180- 角 getsin:lea bx, sintab

xlat

or al, dl

mov rest, al

ret

Page 184: 第一章  概述 第一节  引言

201

P168 例 . 有一个 0! ~7!阶乘法,在某一单元中给定一个值( 0~7 ) 通过查表,找到它的阶乘值。 table dw 1,1,2,6,24,120,720,5040

result dw ?

digit db x

mov bh, 0

mov bl, digit

add bx, bx

lea si, table

mov ax, [si] [bx]

mov result, ax

Page 185: 第一章  概述 第一节  引言

202

八 . 参数传送技术 子程序:说明含有下面的信息 子程序名称、功能、子程序入、出

口参数、子程序使用寄存器、存储区、子程序调用其他子程序的名 称、方式。

一般调用程序向子程序传递有关参数是指: 子程序操作时需要的数据或数据的地址,以便子

程序根据这些参数完成有关操作。

1. 寄存器方式 参数传递方式 2. 存储器方式 3. 堆栈方式

Page 186: 第一章  概述 第一节  引言

203

(一)寄存器(调用程序与子程序之间通过寄存器传送参数) 若一个子程序要对 2 个长度相同的数据区进行操作 那么在主程序中:把长度首地址→内部寄存器 mov cx, length buffer

mov bx, offset buffer1

mov si, offset buffer2

call subr

(二)存储器(要传送的参数直接放在子程序调用指令之后) call subr

dw bufl: 缓冲区长度 dw bufa: 区 A起始地址 dw bufb: 区 B起始地址 此法取参数,必须从堆栈中取出返回地址( call 下一条指令

地址) 取出参数,修改返回地址以指向其真正要执行的指令地址。

-L--A-

-B-

Page 187: 第一章  概述 第一节  引言

204

子程序: push bp

mov bp, sp

mov bx, [bp+2] 从栈中取出返回地址(即参数所在地址) mov cx, CS:[bx] cx←长度 mov s1, CS :[bx+2] A→s1 mov d1, CS:[bx+4] B→d1 add bx, 6 6=3*2 个字节 mov [bp+2], bx 修改返回地址,使子程序能返回至所传送参数

后 面的

指令 ret

……

Page 188: 第一章  概述 第一节  引言

205

(三)利用堆栈传送参数 date seg buffer1 dw BUFA buffer2 dw BUFB buf dw BUFL date ends 主程序: lea bx, buffer1 push [bx] push [bx+2] push [bx+4] call subr 子程序: push bp (subr) mov bp, sp mov cx, [bp+4] cx←BUFL mov d1, [bp+6] d1←BUFB mov s1, [bp+8] s1←BUFA

Page 189: 第一章  概述 第一节  引言

206

九 . 子程序设计 若一个子程序能够被中断或被中断程序调用,称此子程序

为能 重入。 系统利用堆栈和寄存器来存放临时的数据就能够实现重入。

主程序s

start

Call SR1

Call SR2

Call SR1

END

子程序 1SR1 PROC

ret

子程序 2SR2 PROC

ret

返回点地址的入栈和出栈都是自动实现的。子程序调用自己称为递归,递归必须是重入的。

Page 190: 第一章  概述 第一节  引言

207

P172. 例 . 64 位加法 stack

db 100 dup (?)

stack ends

code segment

assume cs: code, ss: stack

start proc far

begin: push ds

mov ax, 0

push ax

call add64

num1 dd x1, x2

num2 dd y1, y2

buffer dd ?, ?

ret

start endp add64 proc push bp mov bp, sp pushf 保存 f push ax push cx 保存寄存器 push bx mov bx, [bp+2] bx←num1 首地址 push bx 首地址入栈 add bx, 18H bx←首地址 +24 修改返回地址 mov [bp+2], bx 存入修改地址

Page 191: 第一章  概述 第一节  引言

208

Pop bx 首地址出栈 Mov cx, 4 一次取 16位, 64位 取 4 次 Clc c=0

Again: mov ax, cs: [bx]

adc ax, cs: [bx+8]

mov cs: [bx+10H], ax

inc bx

inc bx

loop again

pop bx pop cx 恢复寄存器 pop ax

popf 恢复 f pop bp

ret

add64 endp

Page 192: 第一章  概述 第一节  引言

209

注意: 1 )定义须考虑段地址,段内偏移量(默认 DS ) 2 )取地址是在程序段定义的,故用 CS : [BX] 3 )主程序的调用子程序指令指入的是 CALL 指令的下一单 元地址(不是正确返回地址),所以要修改返回地址, 以指向真正要执行的指令地址。

P175. 例 . n*(n-1) n>0 1 n=0 push cx

mov ah, 0

mov al, num

call factor mov fnum, ax 积存入 pop cx

Ret Start endp Factor proc push ax sub ax, 1 jne f-cont pop ax

n!=

ax←num

Page 193: 第一章  概述 第一节  引言

210

jmp retam

f-cont:call factor

pop cx

mul cx

retam:ret

factor endp

Page 194: 第一章  概述 第一节  引言

211

数的阶乘: n*(n-1)! 1

name ----

data segment

num db 3

faum dw ?

data ends

stack segment para stack ‘stack’

db 100 dup (?)

stack ends

code segment

assume: cs: code, ds:data,

es:data, ss: stack

stack proc far

Begin: push ds mov ax, 0 push ax mov ax, data mov ds, data mov es, data push cx mov ah, 0 mov al, mun call factor mov faum, ax pop cx ret

n!=

Page 195: 第一章  概述 第一节  引言

212

start endp

f-cont:call factor

pop cx

mul cl

:ret

factor proc

push ax

sub ax, 1

jne f-cont

pop ax

jmp return

return:ret

factor endp

end begin

Page 196: 第一章  概述 第一节  引言

213

无条件转移 JMP SHORT DST

段内直接短转移, -128~+127范围相对转移,

DST 为标号 1. 如: JMP SHORT OVER

JMP NEAR PTR DST

段内直接近转移, -32K~+32K范围相对转移,

DST 为标号

JMP DST 段内间接转移 64KB范围绝对转移, DST 为寄存器 2. 如: JMP CX

JMP WORD PTR DST 段内间接转移 64KB范围绝对转移, DST 为存储单元 如: JMP WORD PR

T [1234H]

段内直接转

段内间接转移

Page 197: 第一章  概述 第一节  引言

214

段间直接转移: JMP FAR PTR DST 段外绝对转移 DST 为另一个代码段中的标

把 DST所在段的值→ CS

DST偏移量的值→ IP

段间间接转移: JMP DWORD PTR DST 段外绝对转移 DST 为存储单元 如: JMP DWORD PTR [1234H] 低

字内容→ IP

高字内容→ CS

条件转移指令均为段内短转移,范围为: -128~+127

1. JMP WORD PTR [DI] 是 ( )2. JMP FAR PTR ABCD (符号地址)是 ( )A. 段内间接转移 B. 段间间接转移C. 段内直接转移 D. 段间直接转移

习题:

Page 198: 第一章  概述 第一节  引言

215

十 . I/O 的 DOS 功能调用 调用:把子程序的号(系统功能调用号)→ AH

把子程序规定的入口参数送至指定寄存器 再由中断指令 INT 21H

如: lea dx string mov AH 9 显示字符串 DS: DX int 21H

如: mov dl, outpot-char

mov AH, 2 int 21H 它要求把要输出的字符的 ASCII码送至 DL DOS功能调用向 CRT 输出一个字符的子程序 lea DX, buffer 输入缓冲区的

指针 从键盘输入的一个字符串 mov AH, 10 int 21H

DX→ 规定长度实际长度

字符

Page 199: 第一章  概述 第一节  引言

216

P179. 例 .软件时钟程序 buffer db 10 规定缓冲区长度为 10 字节 db ? 实际输入长度单元 db 10 dup (?) 存放输入字节 mov ax, data mov ds, ax 置初值 mov es, ax

mov dl, ‘:’ mov ah, 2 显示“:” int 21H lea dx, buffer ( DS:DX)=缓冲区最大 mov ah, 10 字符数,( DS:DX+1) int 21H =实际输入字符数 lea bx, buffer+2 存放输入字符首地 址→ buffer+2

mov al, [bx]

and al, 0FH

mov [bx], al inc bx ASSII →BCD

mov al, [bx] 码, ××(时)

and al, of

mov [bx], al

inc bx

inc bx

跳过冒号字符

……

……

……

. ×× 分

跳过

××秒

Page 200: 第一章  概述 第一节  引言

217

lea bx, buffer+2 mov al, [bx] call m0110 mov ch, al ch为时值   inc bx

inc bx

mov al, [bx]

call m0110 mov dh, al dh为分值   dl 为秒值 again: call delay mov al, dl al←秒值     add al, 1

daa mov dl, al 秒值增1

cmp al, 60 是否为60 jne dispy 否,转显示 mov dl, 0 是,秒值为0

dispy: lea bx, buffer mov al, 0DH 回车 mov [bx], al  [bx]→回车 inc bx mov al, 0AH mov [bx], al 换行    inc bx mov al, ch 时 call tran BCD→ASCII    inc bx mov al, ‘:’ mov [bx], al inc bx

取 ×× 时的第一个 ×

跳过

…….

……

Page 201: 第一章  概述 第一节  引言

218

mov al, dh 分 call tran

   inc bx

mov al, ‘:’

mou [bx], al

inc bx mov al, dl 秒 call tran

inc bx

mov al, ‘$’

mov [bx], al

push bx

push cx

push dx

lea dx, buffer

mov ah, 9

int 21H

pop dx

pop cx

pop bx

jmp again

start endp

m0110 proc add al, al al*2 daa

mov cl, al add al, al al*4 daa add al, al al*8

显示字符串 DS:DX

Page 202: 第一章  概述 第一节  引言

219

daa mov cl, al 十位数→ cl inc bx

mov al, [bx]

add al, cl

ret

m0110 endp

tran proc

mov cl, al

shr al, 1

shr al, 1

shr al, 1

shr al, 1 or al, 30H 把十位数→ ASCII码   mov [bx], al

mov al, cl and al, of or al, 30H 把个位数→ ASCII mov [bx], al ret tran endp delay proc push cx push ax mov cx, 0FFFFH goon: dec cx jne goon pop ax pop cx ret delay endp

Page 203: 第一章  概述 第一节  引言

220

十一 .结束用户程序返回DOS方法    1 .mov AH, 4CH int 21H 用功能调用 4CH(程序结束后插入以上语句)   2 .int 20H 返回DOS子程序,用中断调用 20H   3 .jmp 0 转移到0单元(程序段前缀的开始处,0单元放的是一条            int 20H)     start proc far begin: push DS mov AX, 0 push AX ret start endp

… 同 int 20H

弹出开始推入的 AX(0000)和 DX

Page 204: 第一章  概述 第一节  引言

221

  4 . 用功能调用 00H

    mov AH, 0

int 21H

十二 . 宏汇编与条件汇编  (一) .宏指令的用途    1 .宏指令可代替源程序重复使用的程序段       mov cl, 4

sal al, cl

由于要多次使用,用一条宏指令代替如下:       SHIFT MACRO

mov cl, 4

sal al, cl

ENDM

=JDMP 0

宏定义的名

定义符

宏定义的体:宏指令代替的程序段

结束符

Page 205: 第一章  概述 第一节  引言

222

         指令语句(执行语句)          伪指令(管理语句)    凡要实现 mov cl, 4; sal al, cl 的内容,可以用 SHIFT

(宏汇编程序调用时,产生目标代码)   2 .宏定义不仅简洁方便,而且具有接受参量的能力      SHIFT MACRO *   ( * 是形式参量) mov cl, *

sal al, cl

ENDM

     SHIFT 4 实现移位4次      若 SHIFT MACRO *, Y Y代替需要以为的寄存器           mov cl, *

sal Y, cl

ENDM

宏定义的体

Page 206: 第一章  概述 第一节  引言

223

SHIFT 4, AL SHIFT 6, BX

mov cl, 4 mov cl, 6

sal, AL, cl sal BX, cl

汇编时分别产生目标代码 3.形式参量可以在操作码部分中出现 如: SHIFT MACRO X, Y, Z mov cl, X S&Z Y, cl 定义为形式参数,前面必须加上符号&

ENDM 参数 Z用来指示操作码的操作 MOV CL, 4 SAL AL, CL MOV CL, 6 SAR BX, CL MOV CL, 8 SHR SI, CL

SHIFT 4, AL,AL

SHIFT 6, BX, AR

SHIFT 8, SI, HR

Page 207: 第一章  概述 第一节  引言

224

(二)宏操作伪指令 1. MACRO/ENDM 宏定义伪指令 格式: 宏定义名 MACRO 〈形式参量表〉 MACRO与 ENDM成对出现 2. PURGE 取消宏定义 格式: PURGE 宏定义名 [,…… ] 3. LOCAL 形式参量表 宏定义体内允许使用标号 CHANGE MACRO AL中有一位 16进制数转换 ASCII

CMP AL, 10 JL ADD-0 ADD AL,’ A’-’0’-10 ADD AL, 0 ENDM 格式: LOCAL 形式参量表 必须是 MACRO后的第一个语句,其间不允许分号和注释

重复定义在宏汇编内是不允许的

错误重复定义

Page 208: 第一章  概述 第一节  引言

225

CHANGE MACRO LOCAL ADD-0

展开时为: + CMP AL, 10 + JL ?? 0000 + ADD AL, ’A’-’0’-10 + ?? 0000 ADD AL,’0’

+ CMP AL, 10 + JL ?? 0001 + ?? 0001 4.REPT/ENDM 重复块伪指令 格式: REPT 〈表达式〉 ENDM

插入

指令体(重复体)

Page 209: 第一章  概述 第一节  引言

226

重复执行指令体所包含的语句,重复次数为〈表达式〉值决定

如: 把 1-10 分配给十个连续的存储单元 X=0 REPT 10 X=X+1 DB X ENDM 5. IRP/ENDM 常参数重复块伪指令 格式: IRP 形式参量(参数表 ) 指令体 ENDM 重复次数由参数的个数所决定,每重复一次,用表中参数代 替形式参量 如: IRP X 〈 1 , 2, 3, 4, 5, 6, 7, 8, 9, 1

0〉 DB X ENDM 把 1-10 分配给 10个连续的存储单元

Page 210: 第一章  概述 第一节  引言

227

6. IRPC/ENDM 串重复块伪指令 格式: IRPC 形式参量,字符串(或〈字符串〉) ENDM 重复次数取决于字符串中字符的个数,且每次重复,依次把 字符串中的字符代替形式参量 如: 把 1-10 分配给 10个连续单元 IRPC X, 0123456789 DB X+1 ENDM (三)宏定义嵌套 可以嵌套在宏定义中利用宏调用(先定义) DIF MACRO N1 , N2 MOV AX, N1 SUB AX, N2 ENDM

指令体

Page 211: 第一章  概述 第一节  引言

228

DIFSQR MACRO N1 , N2 , RSULT PUSH DX PUSH AX DIF N1 , N2 IMUL AX MOV RESULT, AX POP AX POP DX ENDM 另外,宏定义还可以包含宏定义 DIFMALOT CACRO OPNA, OPRAT OPNA MACRO X, Y, Z PUSH AX MOV AX, X OPRAT Z, AX

Page 212: 第一章  概述 第一节  引言

229

POP AX ENDM ENDM 若有宏调用: DIFMALOT ADDITION, ADD 汇编展开为: ADDITION MACRO X, Y, Z PUSH AX MOV AX, X ADD Z, AX POP AX ENDM 同样,它可以用于定义算术与逻辑运算指令 (四)宏指令与子程序的区别 子程序:汇编后产生目标代码少,即目标程序占用的内

存 空间少,节约内存,但每次调用需要恢复保护, 恢复现场,执行时间长,速度慢。

Page 213: 第一章  概述 第一节  引言

230

宏指令:汇编时,把宏指令体插入到宏调用处,有多少次宏

调用,在目标产许需要同样多次的目标代码输入。 所以,宏指令目标程序长,占用内存多,但不需

要 保护断点,执行时间短,速度快。 (五)条件汇编 IF XX ARGUMENT ←条件 语句体 1 ELSE 任选 语句体 2 ENDIF IF 〈表达式〉≠ 0 为真 IFE 〈表达式〉 =0 为真 IF1 扫描第 1遍的过程中 为真 IF2 扫描第 2遍的过程中 为真

……

Page 214: 第一章  概述 第一节  引言

231

IFDEF 〈符号〉 指定符号被定义为真 IFNDET 〈符号〉 指定符号未被定义为真 INB 〈参量〉 空格 IFNB 〈参量〉 IFIDN 〈参量 1〉 〈参量 2〉 =2 为真 INDIF 〈参量 1〉 〈参量 2〉 ≠ 2 为真 (六)举例 P200. 例 3-36 64位加法 add64 macro n1,n2,buffer lea bx,n1 mov cx,4 clc again: mov ax,[bx] adc ax,[bx+8] mov [bx+10H],ax

Page 215: 第一章  概述 第一节  引言

232

inc bx inc bx loop again endm data add64 num1,num2,buffer ret

begin: push as mov ax,0 push ax mov ax,data mov ds,ax mov es,as add64 num1,num2,buffer 宏调用

……