53
21 世世世世世世世世世世 世世世世世世世世 世世 世世世 世世世 世世世 世世世世世世世世世

21 世纪高等院校规划教材

  • Upload
    yvonne

  • View
    94

  • Download
    0

Embed Size (px)

DESCRIPTION

21 世纪高等院校规划教材. 汇编语言程序设计. 相 伟 主编 徐小平 李珍香 副主编. 中国水利水电出版社. 第 4 章 分支程序设计. 本章主要讲解分支程序设计的基本思想和设计方法。通过本章学习,读者应掌握以下内容: 段内寻址与段间寻址 无条件转移指令 条件转移指令 二分支程序设计方法 多分支程序设计方法. 4.1 转移地址的寻址方式. - PowerPoint PPT Presentation

Citation preview

Page 1: 21 世纪高等院校规划教材

21 世纪高等院校规划教材

汇编语言程序设计相 伟 主编徐小平 李珍香 副主编

中国水利水电出版社

Page 2: 21 世纪高等院校规划教材

第 4 章 分支程序设计 本章主要讲解分支程序设计的基本思想和设计

方法。通过本章学习,读者应掌握以下内容: 段内寻址与段间寻址 无条件转移指令 条件转移指令 二分支程序设计方法 多分支程序设计方法

Page 3: 21 世纪高等院校规划教材

4.1 转移地址的寻址方式 Intel 8086/8088CPU 中,程序的执行顺序是由代码段

寄存器 CS 和指令指针 IP 确定的。 CS 包含当前指令所在代码段的段地址, IP 则是要执行的下一条指令的偏移地址。通常情况下,程序是顺序执行的,即 CPU取出指令后,自动形成下一条指令的地址,依指令序列顺序执行。但有时需要改变程序的流程,这就要给出目标指令的段地址( CS )和偏移地址( IP )值,这就是与转移地址有关的寻址方式。

与转移地址有关的寻址方式有四种:段内直接寻址、段内间接寻址、段间直接寻址和段间间接寻址。

Page 4: 21 世纪高等院校规划教材

4.1.1 段内寻址 段内寻址分为段内直接寻址和段内间接

寻址两种方式。其转移方式是在当前代码段 64KB 范围内转移,因此不需要更改段地址 CS 的值,只要改变偏移地址 IP 的值即可。

Page 5: 21 世纪高等院校规划教材

1 .段内直接寻址 指令中直接给出转移地址的偏移量( 8 位或 16 位),转

移目标与转移指令在同一段内。转移指令执行后, CS 值保持不变。转移的有效地址为当前的 IP 值与指令中指定的偏移量之和。即

目标地址 = IP (当前值) + 偏移量 其中偏移量为 8 位或 16 位有符号数。若偏移量为正数,

向前转移(即高地址方向);若偏移量为负数,则向后转移(即低地址方向)。另外,对 8 位偏移量,其转移范围为 -128 ~ +127 ,称为短转移;对 16 位偏移量,其转移范围为 -32768 ~ +32767 ,称为近转移。

短转移指令为 2 字节指令, IP 的当前值为转移指令所在的 IP 值加 2 。近转移指令为 3 字节指令, IP 的当前值为转移指令所在的 IP 值加 3 。

Page 6: 21 世纪高等院校规划教材

例 4-1 :分析下列指令。 JMP SHORT DSP1 ;短转移指令 JMP NEAR PTR DSP2 ;近转移指令

假设两条指令存放地址均为 1000H:0200H ,偏移量 DSP1 为 08H ,偏移量 DSP2 为 0012H 。

短转移指令执行时, 当前 IP 值 = 0200H + 2 = 0202H 。 目标地址 = IP (当前值) + 偏移量 = 0202H + 08H = 020AH 指令执行后将转向 1000H:020AH 去执行。 近转移指令执行时, 当前 IP 值 = 0200H + 3 = 0203H 。 目标地址 = IP (当前值) + 偏移量 = 0203H + 0012H = 0215H 指令执行后将转向 1000H:0215H 去执行。

Page 7: 21 世纪高等院校规划教材

2 .段内间接寻址 与段内直接寻址方式相同,转移目标与

转移指令在同一段内。转移指令执行后,CS 值保持不变。与段内直接寻址方式不同的是,转移的有效地址值存放在 16 位的通用寄存器或连续两个存储单元中。若有效地址在存储单元中,一定要指出存储单元为字型。

Page 8: 21 世纪高等院校规划教材

例 4-2 :假设( DS ) =2000H ,( BX ) =3000H ,( 23000H ) =2536H ,分析下列指令。

JMP BX 指令执行后,将 BX 的内容直接赋给 IP 。所以,( IP ) = 3000H 。

JMP WORD PTR[BX] 指令执行后,先计算出存储单元地址 23000H ,

再从该单元中取出内容送给 IP 。所以,( IP ) = 2536H 。

Page 9: 21 世纪高等院校规划教材

4.1.2 段间寻址 段间寻址分为段间直接寻址和段间间接

寻址两种方式。其转移方式是从当前代码段跳转到另一个代码段,因此需要修改 CS 段地址和 IP 偏移地址的值。

Page 10: 21 世纪高等院校规划教材

1 .段间直接寻址 在指令中直接给出了转移目标的段地址

和偏移地址。只要用指令中指定的偏移地址代替 IP 寄存器的内容,用指令中指定的段地址代替段寄存器 CS 的内容就可以完成从一个段到另一个段的转移操作。段间直接转移通常叫远转移( far jump),指令的操作数必须附加 FAR PTR操作符。

Page 11: 21 世纪高等院校规划教材

例 4-3 :执行如下指令 JMP FAR PTR DSP 假设指令存放地址为 1000H:0200H ,

DSP 的有效地址为 3620H ,段地址为 2000H 。

则指令执行后, ( IP ) = 3620H ,( CS ) = 2000H 。

程序转移到 2000H:3620H处继续执行。

Page 12: 21 世纪高等院校规划教材

2 .段间间接寻址

与段间直接寻址方式相同,转移目标与转移指令不在同一段内,转移指令执行后, CS 和 IP都发生变化。不同的是转移目标的偏移地址和段地址存储在两个连续的字存储单元中。因此指令中需要用 DWORD PTR 操作符将存储单元指定为双字单元。指令执行时,根据存储单元的寻址方式计算出存储单元地址,从该存储单元取第一个字传送到 IP ,取第二个字传送到 CS ,这样就可以实现段间转移。

Page 13: 21 世纪高等院校规划教材

例 4-4 :执行如下指令

JMP DWORD PTR 6[BX] 假设:( CS ) = 1000H ,( IP ) = 0600H ,

( DS ) = 2000H ,( BX ) = 1000H ,( 21006H ) = 3000H ,( 21008H ) = 6000H 。

则指令执行后, ( CS ) = 6000H ,( IP ) = 3000H 。 程序转移到 6000H:3000H处继续执行。

Page 14: 21 世纪高等院校规划教材

4.2 无条件转移指令 无条件转移指令 JMP使 CPU 无条件地转移到指令

中指明的目的地址处执行。它不能构成分支程序,但在分支程序中却往往需要用它将各分支的出口重新汇集到一起。特别是当条件转移指令的转移范围超过 -128 ~ +127 个字节时,往往要借助无条件转移指令实现预定的转移。

转移可分成两类:段内转移和段间转移。段内转移是指在同一代码段内进行转移,此时只需改变 IP寄存器的内容,即用新的转移目标地址代替原有的IP 值就可达到转移的目的。段间转移则是要转到另一个段去执行程序,此时不仅要修改 IP 寄存器的内容,还需要修改 CS 寄存器的内容才能达到目的。因此,此时的转移目标地址应该由新的段地址和偏移地址两部分组成。

Page 15: 21 世纪高等院校规划教材

4.2.1 段内无条件转移

1 .段内直接转移 指令格式: ① JMP 标号 ; IP←( IP ) + 位移量 ② JMP SHORT 标号 ; IP←( IP ) +8 位位移量,短转移 ③ JMP NEAR PTR 标号 ; IP←( IP ) +16 位位移量,近转移 功能:无条件地转移到指令指定的标号处,执行

从该标号开始的指令。 其中: JMP 为指令操作码。标号为 8 位或 16 位

偏移量。

Page 16: 21 世纪高等院校规划教材

2 .段内间接转移 指令格式: ① JMP 寄存器 ② JMP WORD PTR 存储单元 功能:程序转移的有效地址放在寄存器

或存储单元中,执行指令时,将寄存器或字存储单元中的有效地址写入 IP ,从而实现转移。

Page 17: 21 世纪高等院校规划教材

4.2.2 段间无条件转移1 .段间直接转移 指令格式: ① JMP 标号 ② JMP FAR PTR 标号 功能:无条件地转移到另一个代码段的

标号处,执行从该标号开始的指令。标号所在段的段地址作为新的 CS ,标号在该段内的偏移地址作为新的 IP 。

Page 18: 21 世纪高等院校规划教材

2 .段间间接转移

指令格式: JMP DWORD PTR 存储单元 功能:指令执行时,从指定存储单元连

续取出两个字,第一个字送给 IP ,第二个字送给 CS ,从而实现段间转移。

JMP 指令不影响状态标志位。

Page 19: 21 世纪高等院校规划教材

4.3 条件转移指令 条件转移指令根据上一条指令所设置的条件标志作判断依据,条件满足则程序转移,否则顺序执行。这类转移指令的转移均属于短转移,即转移目标地址距当前 IP 所表示的地址的距离为 -128 ~ +127 字节。

语句格式为: 助记符 标号 条件转移指令共有 18 条,可分成以下三类: ① 简单条件转移指令。 ② 无符号数条件转移指令。 ③ 有符号数条件转移指令。 条件转移指令均不影响状态标志位。

Page 20: 21 世纪高等院校规划教材

4.3.1 简单条件转移指令

简单条件转移指令共有 10 条指令。它们是根据 5 个标志位 CF、 ZF、 SF、 OF、PF的两种状态( 1 或 0 )而设置的。一般适用于测试某一次运算结果的状态,并根据不同的状态标志产生不同的分支进行处理。

下面分别举例说明。

Page 21: 21 世纪高等院校规划教材

例 4-5 :假设 AX 中为一带符号数,求 AX中数的绝对值。

分析:求一个数的绝对值时,首先要测试该数的正负。我们可以测试其最高位,也可以测试符号标志。因此以下两个程序段均可求出 AX 中数的绝对值。

程序段 1 : TEST AX , 8000H JZ NEXT ;测试 AX最高位,为零该数为正,转到 NEXT NEG AX ;否则, AX 为负,求补运算 NEXT : …… …… 程序段 2 : AND AX , AX ;影响标志位 JNS NEXT ;测试 AX 的符号位,为正则转到 NEXT NEG AX ;否则, AX 为负,求补运算 NEXT : …… ……

Page 22: 21 世纪高等院校规划教材

例 4-6 :计算 X+Y, X 和 Y单元分别存放着一个 16 位有符号数。若结果有溢出,则转移到 OVERFLOW处理。

分析:两个有符号数相加,影响 OF的值。若OF 置 1 ,则产生溢出。

程序段如下: MOV AX , X ADD AX , Y JO OVERFLOW …… ;没有溢出,结果正确 OVERFLOW :…… ;溢出处理

Page 23: 21 世纪高等院校规划教材

例 4-7 :统计寄存器 BX 中 1 的个数。 分析:要统计寄存器 BX 中 1 的个数,可以通过移位指

令将 BX 中的每一位依次移入 CF中,若 CF=1 则 CL的值加 1 。这样就可以统计出 BX 中 1 的个数。

程序段如下: MOV CL , 0 ;保存 BX 中 1 的个数,初值为 0 AGAIN : AND BX , BX JZ EXIT ,( BX ) = 0 时,结束循环转 EXIT SAL BX , 1 ;将 BX 中的最高位移入 CF中 JNC AGAIN ;如果 CF= 0 转 AGAIN INC CL ;否则, CL的值加 1 JMP AGAIN ;转 AGAIN处继续处理 EXIT : ……

Page 24: 21 世纪高等院校规划教材

4.3.2 无符号数条件转移指令

这类指令往往跟在比较指令之后,视比较对象为无符号数。根据比较结果的不同状态,设置了高于( A-Above )、高于或等于( AE-Above or Equal )、低于( B-Below)、低于或等于( BE-Below or Equal )四条指令。

Page 25: 21 世纪高等院校规划教材

无符号数条件转移指令 ① JA/JNBE 用于两个无符号数 a 、 b的比较,若 a>b则条件满足,实现转移。 ② JNA/JBE 用于两个无符号数 a 、 b的比较,若 a≤b则条件满足,实现转移。 ③ JB/JNAE 用于两个无符号数 a 、 b的比较,若 a<b则条件满足,实现转移。 ④ JNB/JAE 用于两个无符号数 a 、 b的比较,若 a≥b则条件满足,实现转移。

四条指令的共同点是根据两个无符号数比较的结果,判断 CF、 ZF的状态是否满足转移条件,当满足条件时转移,否则顺序执行。适用于地址比较、循环次数比较或双精度数的低位字的比较等。

Page 26: 21 世纪高等院校规划教材

例 4-8 :阅读下面程序段,若寄存器 AL的值分别取 20H 、 5 、 0FFH 和 2 ,分析程序段的执行情况。

程序段如下: CMP AL , 5 JA NEXT ADD AL , 5 NEXT :……

分析:本程序段使用了无符号数跳转指令 JA ,若( AL)> 5则转 NEXT ,否则顺序执行。

( 1 )( AL) = 20H> 5 ,满足条件,跳至 NEXT处执行。 ( 2 )( AL) = 5 ,不满足条件,顺序执行“ ADD AL, 5 ”。 ( 3 )( AL) = 0FFH ,由于 JA 是无符号数跳转指令,对无符

号数来说( AL) = 0FFH> 5 ,满足转移条件,故跳转至 NEXT处执行。

( 4 )( AL) = 2< 5 ,不满足条件,故顺序执行后继指令。

Page 27: 21 世纪高等院校规划教材

例 4-9:分析以下程序段: MOV SI , 0 ; SI←0 JP : MOV WORD PTR [SI] , 0 ; [SI] ←0 ADD SI , 2 ; SI←( SI ) +2 CMP SI , 0F000H ;判断( SI )是否小于等 于 0F000H JNA JP ;若小于等于,则转 JP 执行 ……

分析:该程序段的功能是将当前数据段中偏移地址为 0 ~ 0F000H 的全部字存储单元清 0 ,其中 SI 为送数指针。

注意:在比较判断( SI )是否小于等于 0F000H 时,由于地址是无符号数,所以必须选用无符号数条件转移指令 JNA ,才能完成预定功能。

Page 28: 21 世纪高等院校规划教材

4.3.3 带符号数条件转移指令

在程序设计中,有时需要把处理对象视为带符号数(补码表示)。当比较两个带符号数的大小时,要选用带符号数条件转移指令。带符号数条件转移指令是根据条件标志ZF、 SF、 OF的特定组合来决定是否转移,共设置了大于、大于或等于、小于、小于或等于四条指令。

Page 29: 21 世纪高等院校规划教材

带符号数条件转移指令 ① JG/JNLE 用于两个有符号数 a 、 b比较。若 a>b,即符号标志 SF与溢出标志 OF具有相同状态( SF=OF)且零标志ZF=0 时,条件满足,实现转移。 ② JNG/JLE 用于两个有符号数 a 、 b的比较。若 a≤b,即当 SF≠OF或 ZF=1 时,条件满足,实现转移。 ③ JL/JNGE 用于两个有符号数 a 、 b的比较。若 a<b,即当 SF≠OF时,条件满足,实现转移。 ④ JNL/JGE 用于两个有符号数 a 、 b的比较。若 a≥b,即当 SF=OF时,条件满足,实现转移。

四条指令的共同点是根据两个带符号数比较运算的结果,组合 SF、OF标志,并利用 ZF标志确定转移与否。

下面举例说明条件转移指令的使用方法。

Page 30: 21 世纪高等院校规划教材

例 4-10 :假设有两个双精度数 a 和 b,分别存储在 AX 、 BX 和 CX 、 DX 中,分析下列程序段的功能。

程序段如下: CMP AX , CX JG UPPER JL LOWER CMP BX , DX JA UPPER LOWER :…… UPPER :…… 图 4-4 比较两个数大小算法流程图

(AX)>(CX)

(AX)<(CX)

(BX)>(DX)

N

N

N

Y

Y

Y

标号 UPPER处 标号 LOWER处

分析:本程序段的功能是比较两个双精度数 a 和 b的大小,若 a﹥b则转向 UPPER 执行,否则转向 LOWER执行。程序段流程图如图 4-4 所示。

Page 31: 21 世纪高等院校规划教材

例 4-11 :将例 4-9程序段中的 JNA 指令改成 JNG指令,分析程序段功能。

程序段如下: MOV SI , 0 ; SI←0 JP : MOV WORD PTR [SI] , 0 ; [SI] ←0 ADD SI , 2 ; SI←( SI ) +2 CMP SI , 0F000H ;判断( SI )是否小于等于 0F000H JNG JP ;若小于等于,则转 JP 执行 ……

Page 32: 21 世纪高等院校规划教材

分析:

该程序段在进行比较判断时,选用了带符号数条件转移指令 JNG。在第一次执行比较指令“ CMP SI , 0F000H ”时,( SI ) = 2 ,它与带符号数 0F000H (即- 1000H )比较,显然 2>- 1000H ,不满足“ JNG”的转移条件而顺序执行后继语句。这样就只能将 0 送入偏移地址为 0 的字单元中,无法实现将当前数据段中偏移地址为 0 ~ 0F000H 的全部字存储单元清 0 。

以上例子说明在设计分支程序时一定要注意正确选择条件转移指令。

Page 33: 21 世纪高等院校规划教材

4.4 分支程序设计方法 在实际应用中,计算机处理的问题不可能全是顺序地执行操作,而往往需要对出现的各种情况进行分析判断,以决定进行不同的处理。这种分不同情况进行不同处理的程序结构就是分支程序结构。

分支程序结构有两种形式,如图 4-5 所示: 图 4-5 分支程序结构示意图

图( a )二分支结构

判定条件为真

NY

分支 1 分支 2

图( b )多分支结构

判定条件

条件 1

分支 2分支 1 分支 n……

条件 2 条件 n

不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种确定条件下,只能执行多个分支中的一个分支。

Page 34: 21 世纪高等院校规划教材

4.4.1 二分支程序设计

所谓二分支程序设计,就是根据判定条件为真或为假,从两条分支中选择一条分支去执行。二分支程序中的一种特殊情况就是只有一个分支程序段,另一个分支是顺序执行,有时也把这种结构称为单分支结构。

Page 35: 21 世纪高等院校规划教材

例 4-12 :分析下列程序段的结构。 CMP AX , 0 JGE DONE ;如果( AX )≥ 0 ,则转 DONE NEG AX ;否则进行求补运算 DONE : MOV RESULT , AX ;保存结果 ……

图 4-6 单分支程序结构示意图

( AX )≥0 为真

Y

Y

AX←-( AX )

RESULT← ( AX )

N 本程序段用来计算 AX 中带符号数的绝对值,是一个典型的单分支结构。程序段流程图如图 4-6 所示:

Page 36: 21 世纪高等院校规划教材

要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分析判断,根据判断结果决定执行哪一个分支,最后转入相应程序段的起始地址去执行分支程序。其中产生条件的指令通常由指令系统中影响状态标志位的指令来产生,如算术运算指令(如 ADD 、SUB 、 CMP )、逻辑运算指令(如 AND 、 TEST )、移位指令(如 SHR 、 SHL)等等。要想用好这些指令,就要搞清楚这些指令的功能及其对标志位的影响。特别是要熟练掌握状态标志位 CF、 ZF、 PF、 SF和OF的含义。

下面我们通过例子来介绍二分支程序设计方法。

Page 37: 21 世纪高等院校规划教材

例 4-13 :从键盘输入 0 ~ 9中任一自然数 x,求其立方值。若输入的字符不是 0 ~ 9中的某数字,则显示“ INPUT ERROR!”,表明输入错误。

分析:求一个数的立方值可以用乘法运算实现,也可以构造一立方表,通过查表实现。此处用查表法,查表法执行速度比较快。

输入数据为 0至 9中任一自然数,用一字节单元存放其值;输出数据是该数的立方值,用一字单元存放其值。若输入时不慎按下 0 ~ 9之外的字符键,则显示错误提示信息。

存储单元和寄存器分配如下: 字节变量 X 中存放键入的自然数 x。 字变量 Y中存放 x的立方值。 AX 是用来存放立方值的工作单元。 BX 是用来进行查表的工作单元。

Page 38: 21 世纪高等院校规划教材

图 4-8 求立方值程序流程图

( AL )是0~9 中某一数

字符

Y

将字符 ASCII 码转换成数字真值

Y←求立方值

N

开始

结束

AL← 从键盘输入字符

显示错误提示信息

假定立方表的首地址为 TAB ,表中共 10项,每项占一个字,用来存放 x的立方值。从表的结构可知, x的立方值在表中的存放地址与 x有如下对应关系:

( TAB+2*x) = x的立方值

对于每个键入的 x,从字单元 TAB+2*x中取出的数据便是其立方值。从键盘接受数字输入使用 1 号系统功能调用,此时送入 AL中的是 x的 ASCII 码,而不是 x的真值。所以要首先将 x的 ASCII 码转换成 x的真值,然后用 TAB+2*x计算x 立方值的存放地址,按此地址查到 x的立方值。程序流程图如图 4-8 所示:

Page 39: 21 世纪高等院校规划教材

源程序如下: STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGMENT INPUT DB ‘PLEASE INPUT X(0..9):$’ TAB DW 0 , 1 , 8 , 27 , 64 , 125 , 216 , 343 , 512 , 729 X DB ? Y DW ? INERR DB 0DH , 0AH ,’ INPUT ERROR !$’ DATA ENDS CODE SEGMENT ASSUME CS:CODE , DS:DATA , SS:STACK BEGIN: MOV AX , DATA MOV DS , AX LEA DX , INPUT MOV AH , 9 INT 21H ; 9号调用显示提示信息 MOV AH , 1 INT 21H ; AL←1 号调用从键盘接受一字符输入

Page 40: 21 世纪高等院校规划教材

CMP AL , ‘ 0’ ;若输入字符不是 0~9中的某一数字,转 LERR JB LERR CMP AL , ‘ 9’ JA LERR AND AL , 0FH MOV X , AL ; X←x的真值 ADD AL , AL MOV BL , AL ; BX←2﹡x MOV BH , 0 MOV AX , TAB[BX] MOV Y , AX ; Y←x的立方值 EXIT: MOV AH , 4CH INT 21H ;结束程序,返回 DOS状态 LERR: MOV DX , OFFSET INERR MOV AH , 9 ;显示错误提示信息 INT 21H JMP EXIT CODE ENDS END BEGIN 程序运行时,屏幕首先显示“ PLEASE INPUT X (0..9):”,若键入 2 ,则 2*x = 4 , 4→BX ,从字单元 TAB+4 中取出 2 的立方值 8 送入 Y中。若键入字符‘ a’,因其不是‘ 0’~‘9’中的某一数字符,故显示“ INPUT ERROR !”。

Page 41: 21 世纪高等院校规划教材

例 4-14 :将 a 、 b、 c 三个十六位无符号数分别与零比较,如果三个数均不为零,求出三个数之和存放在变量 d中(假设总和小于 65535 ),若其中至少有一个数为零,则显示“ ERROR!”。

分析:本题目的程序结构属于双分支结构的嵌套形式,对标志位的判断需要进行两次以上,才能确定其分支。

程序流程图如图 4-9所示。 存储单元和寄存器分配如下: 字变量 A 、 B 、 C 用来存放三个十六位无符号数;

变量 D 用来存放三个数的和; AX 是用来求和的工作单元。

图 4-9 求三个数和的程序流程图

A=0Y

D←求三数和

N

开始

结束

显示” ERROR!”

B=0

C=0

N

N

Y

Y

Page 42: 21 世纪高等院校规划教材

源程序如下:

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGMENT A DW 1234H B DW 5678H C DW 3562H D DW ? INERR DB 0DH , 0AH ,’ ERROR !$’ DATA ENDS CODE SEGMENT ASSUME CS:CODE , DS:DATA , SS:STACK BEGIN: MOV AX , DATA MOV DS , AX MOV AX , 0 ; AX清 0 CMP A , 0 JZ NEXT ; a=0 ,转 NEXT CMP B , 0 JZ NEXT ; b=0 ,转 NEXT

Page 43: 21 世纪高等院校规划教材

CMP C , 0 JZ NEXT ; c=0 ,转 NEXT ADD AX , A ADD AX , B ADD AX , C MOV D , AX ;三数求和,结果存入 D 中 JMP EXIT NEXT: MOV DX , OFFSET INERR MOV AH , 9 INT 21H EXIT: MOV AH , 4CH INT 21H ;结束程序,返回 DOS状态 CODE ENDS END BEGIN 本程序运行时,由于 A 、 B 、 C三个数均不为零,故求出三个数之和 9

E0EH 存放在变量 D 中。读者可任意修改 A 、 B 、 C三个变量的值,比较其运行结果。

Page 44: 21 世纪高等院校规划教材

例 4-16 :假设有三个单字节无符号数依次存放在 BUF1开始的存储区中,试编写程序将它们从大到小排列并依次存放在 BUF2开始的存储区中。

分析(方法一)∶将三个无符号数依次送入 AL、 BL、CL 三个工作单元中,然后在三个工作单元之间比较大小,排好顺序后依次存放在 BUF2开始的存储区中。

程序流程图如图 4-11 所示: 存储单元和寄存器分配如下: BUF1 用来保存原始数据的存储区首址; BUF2 用来存放已排序数据的存储区首址; AL、 BL、 CL用来存放原始数据的工作单元; SI 用来指向 BUF1 的工作指针 DI 用来指向 BUF2 的工作指针。

Page 45: 21 世纪高等院校规划教材

图 4-11 将三个数由大到小排列程序流程图

(AL)≥(BL)

YN

开始

结束

N

YAL 、 BL 、 CL

N

N

将三个数分别送到 AL 、 BL 、 CL 中

(BL)≥(CL) (BL)≥(CL)

(AL)≥(CL) (AL)≥(CL)

AL 、 CL 、 BL

CL 、 AL 、 BL

CL 、 BL 、 AL

BL 、 AL 、 CL

BL 、 CL 、 AL

Y

Y

YN

源程序如下:STACK SEGMENT STACK

DB 200 DUP(0)

STACK ENDS

DATA SEGMENT

BUF1 DB 56H , 12H , 78H

BUF2 DB 3 DUP ( 0 )

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE , DS:DATA , SS:STACK

BEGIN:MOV AX , DATA

MOV DS , AX

MOV SI , OFFSET BUF1 ; SI 指向 BUF1 存储区

MOV DI , OFFSET BUF2 ; DI 指向 BUF2 存储区

MOV AL , [SI]

MOV BL , [SI+1] ;将原始数据分别送入 AL、 BL、 CL

MOV CL , [SI+2]

CMP AL , BL

JAE NEXT1

CMP BL , CL

Page 46: 21 世纪高等院校规划教材

JAE NEXT3 MOV [DI] , CL MOV [DI+1] , BL MOV [DI+2] , AL JMP EXIT NEXT1:CMP BL , CL JAE NEXT2 CMP AL , CL JAE NEXT21 MOV [DI] , CL MOV [DI+1] , AL MOV [DI+2] , BL JMP EXITNEXT2:MOV [DI] , AL MOV [DI+1] , BL MOV [DI+2] , CL JMP EXIT NEXT21:MOV [DI] , AL MOV [DI+1] , CL MOV [DI+2] , BL JMP EXIT NEXT3:CMP AL , CL JAE NEXT31 MOV [DI] , BL MOV [DI+1] , CL MOV [DI+2] , AL JMP EXIT NEXT31:MOV [DI] , BL MOV [DI+1] , AL MOV [DI+2] , CL EXIT:MOV AH , 4CH INT 21H CODE ENDS END BEGIN 程序运行后, BUF2 存储区中依次存储 78H 56H 12H 。

Page 47: 21 世纪高等院校规划教材

由图 4-11 可以看到,用此种方法来比较三个数的大小是非常麻烦的,编程工作量很大。下面我们再来介绍一种简单方法。

Page 48: 21 世纪高等院校规划教材

(方法二): 首先将三个无符号数依次送入

AL、 BL、 CL 三个工作单元中,然后比较 AL和 BL,若 AL小于 BL,则将两者内容交换;再比较 AL和 CL,若 AL小于CL,将两者内容交换,这样 AL中保存的就是三个数中的最大者。再比较 BL与 CL,若 BL小于 CL,就将两者内容交换,即将最小的数放在 CL中。最终将三个数按由大到小的顺序依次存放在 AL、 BL和 CL中。

程序流程图如图 4-12 所示: 存储单元和寄存器分配同方法

一。 源程序如下:

Y

开始

结束

N

将三个数分别送到 AL 、 BL 、 CL 中

图 4-12 将三个数由大到小排列程序流程图

(AL)≥(BL)

( AL )和( BL )交换

(AL)≥(CL)

按 AL 、 BL 、 CL 顺序依次存回

N

( AL )和( CL )交换

N

( BL )和( CL )交换

(BL)≥(CL)

Y

Y

Page 49: 21 世纪高等院校规划教材

STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGMENT BUF1 DB 56H , 12H , 78H BUF2 DB 3 DUP ( 0 ) DATA ENDS CODE SEGMENT ASSUME CS:CODE , DS:DATA , SS:STACK BEGIN:MOV AX , DATA MOV DS , AX MOV SI , OFFSET BUF1 MOV DI , OFFSET BUF2 MOV AL , [SI] MOV BL , [SI+1] MOV CL , [SI+2] CMP AL , BL JAE NEXT1 XCHG AL , BL NEXT1:CMP AL , CL JAE NEXT2 XCHG AL , CL NEXT2:CMP BL , CL JAE NEXT3 XCHG BL , CL NEXT3:MOV [DI] , AL MOV [DI+1] , BL MOV [DI+2] , CL MOV AH , 4CH INT 21H CODE ENDS END BEGIN 读者可对照流程图自己分析源程序。显然第二种方法比较次数更少,编程工作量也大大减少。

Page 50: 21 世纪高等院校规划教材

4.4.2 多分支程序设计

在实际应用中,有时会碰到多分支程序结构。多分支程序结构相当于一个多路开关,有多个并行的分支程序段,每个分支程序段与一个条件相对应,执行时只能执行其中一个分支段。若用条件转移语句实现,则 N 条分支需要 N-1 个条件转移指令完成,转移速度慢,程序代码长。因此常采用地址表法来实现。

地址表法的设计思想是:在程序段中开辟一些存储空间,形成一张地址表,用于依次存放各分支程序段的程序入口地址。程序执行时,首先判断出满足某分支程序段的条件,由此求出该分支程序段的编号。该编号乘 2 (段内转移),或乘 4 (段间转移)得到相对地址表的偏移量,再加上地址表首地址,即得到地址表中的一个地址。在这个地址表地址中存放着分支程序段的偏移地址(或偏移地址 + 段地址),转到该地址去执行程序,即执行该分支程序段。

Page 51: 21 世纪高等院校规划教材

例 4-17 :设计一个程序,根据键盘输入的 1 ~ 9数字转向 9个不同的处理程序段。 分析:在数据段定义一个存储区,形成一地址表,用来存放 9个处理程序段的起始地址。将键盘输入的 1 ~ 9数字符转换为真值,用于查表得到偏移地址。若输入非法字符则提示出错。

程序流程图如图 4-13 所示: 源程序如下: STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS

图 4-13 多分支结构程序流程图

是数字字符?

1

计算转移地址,转向 P02计算转移地址,转向 P01 计算转移地址,转向 P09……

2 9

Y

开始

结束

显示错误提示信息

AL← 从键盘输入一个字符

数字 =?

N

Page 52: 21 世纪高等院校规划教材

CODE SEGMENT ASSUME CS:CODE , DS:DATA , SS:STACK BEGIN:MOV AX , DATA MOV DS , AX LEA DX , INPUT MOV AH , 9 INT 21H ; 9号调用显示提示信息 MOV AH , 1 INT 21H ; 1 号调用从键盘接受一字符输入 CMP AL , ‘ 1’ ;若输入字符不是 1~9中的某一数字,转 LERR

JB LERR CMP AL , ‘ 9’ JA LERR AND AX , 000FH ;将 ASCII 码转换成数字 DEC AX ADD AX , AX MOV BX , AX JMP TAB[BX] ;查表,段内间接转移 EXIT:MOV AH , 4CH INT 21H LERR:MOV DX , OFFSET INERR MOV AH , 9 INT 21H JMP EXIT P01 : ……; 各处理程序入口

P02 : …… …… …… P09 : …… CODE ENDS END BEGIN

Page 53: 21 世纪高等院校规划教材

本章小结 本章主要介绍了与转移有关的寻址方式、

转移指令,以及分支程序设计的基本思想和设计方法。通过本章的学习,一定要熟练掌握无条件转移指令和条件转移指令,正确理解转移指令的功能和使用条件,分清无符号数的条件转移指令和带符号数的条件转移指令的区别,熟练掌握分支程序设计。