第十章 分支程序设计第一节 分支程序结构
1.分支程序结构有两路分支与多路分支两种结构形式。
(1)两路分支完成两种情况的选择处理,相当于高级语言中的 IF-
THEN-ELSE语句,如图 5一 l所示。
(2)多路分支完成多种情况的选择处理,相当于高级语言中的两路分支嵌套结构,CASE语句或 SWITCH语句,如图 5— 2所示 。
(3)分支结构程序要求先进行条件判断,然后根据判断结果将程序的执行流程转移到相应的分支上去,判断一次只可能有一路分支被选择。
第二节 无条件转移指令
1.转移指令分为无条件转移指令和条件转移指令两种。它们通过改变 CS和 IP,或通过仅改变 IP来实现转移。前者适用于段间转移,后者适用于段内转移。
无条件转移指令的功能是将控制无条件地转移到操作数所指位置。
无条件转移指令包括 JMP,CALL和 RET 3条指令,本节只讨论 JMP指令,CALL
和 RET
指令将在第 7章子程序中讨论。
瓜 IP指令的格式为,JMP DOPD
其中,DOPD是转移地址,可以是标号,也可以是寄存器或存储器,前者称为直接转移,
后者称为间接转移。
(1)段内直接短转移,JMP SHORTPTR标号转移地址 IP由当前 IP,加 8位位移量形成,只能在段内 -128~ 127字节的范围内转移。向前转移可缺省 SHORT。
(2)段内直接转移,JMP NEAR PTR标号转移地址 IP由当前 IP加 16位位移量形成,转移位置可以在代码段内任何位置。
(3)段内间接转移,JMP WORD PTR寄存器或内存单元转移地址口位于一通用寄存器中或任一种存储器寻址方式确定。
(4)段间直接转移,JMPFARPTR标号转移时同时修改 IP与 CS。标号必须定义为 FAR属性。
(5)段间间接转移,JMP FARPTR存储器转移地址是内存中的一双字,高位字是转移地址的 CS值,低位字是转移地址的 IP值例 5-1】 JMP指令举例。
C1)JMP SHORTPTR L1;段内短转移
(2)JMP NEAR PTR L2;段内直接转移
(3)JMPFARPTRL3;段间直接转移
(4)JMP DWORD PTR【 Bx];段间间接转移
(5)JMPWORDPTRBX;段内间接转移
(6)JMP DWORD PTR[BP+12];转移到地址在堆栈段的程序
(7)JMP DWORD PTR[BP]【 DI];段间间接转移
JMP指令对标志位无影响。
JMP指令不能构成分支程序,但在分支程序设计中往往需要用它将各分支的出口汇集到一起。另外当条件转移指令的转移范围超过 -128~ +127字节时,也往往要借助 JMP指令来实现预定的转移。
JMP指令虽然变化不少,但大多数时候只用到,JMP标号,的简单形式。
第 3节 条件转移指令
1.概述
( 1) 与无条件转移指令不同,条件转移指令是根据前面形成的条件来确定转移去向。
( 2)条件转移指令的条件主要由标志寄存器给定,根据 ZF,CF,SF、
OF及 PF等标志位的值来转移。能改变这些标志位的运算和指令均可形成转移条件,CMP,TEST指令常用于形成转移的条件。 CX的值是否为 0也常表示转移条件。
( 3) 条件转移指令共有 19条,分为简单条件转移指令、无符号数条件转移指令、符号数条件转移指令及 CX条件转移指令 4类。
( 4)所有条件转移只能是段内直接短转移,而且与 JMP指令一样不影响任何标志位。
( 5)条件转移指令的一般格式为:条件转移指令助记符短标号
2.简单条件转移指令简单条件转移指令是仅取决于 ZF,CF,SF,OF及 PF中某一标志位的条件转移指令。标志 ZF,CF,SF,OF及 PF的值可以表示 10种状态,因而设置了 10条简单条件转移指令,见表 5-1。
【 例 5— 2】 简单条件转移指令举例。
CMP AX,0
JELl; AX为 0时转 L1
ADD AX,1234H
JOL2;溢出时转 L2
3.无符号数条件转移指令无符号数条件转移指令视比较对象为无符号数,往往跟在比较指令后。
对无符号数条件转移指令的,比较,用高于 (Above)、低于 (BelOW)和等于 (Equal)
表示,见表 5— 2,表中 A,B为无符号数。
【 例 5— 3】 X,Y为无符号数,计算 l X-Y l。
程序段如下:
MOV AX,X
CMP AX,Y比较
JAELLL
XCHG AX,Y:如果 AX<Y,交换 AX,Y
LLL,SUBAX,Y
4.符号数条件转移指令当要根据两个符号数的大小关系决定是否转移时,必须选用符号数条件转移指令。
对符号数条件转移指令的,比较,用大于 (Greater)、小于 (Less)和等于
(Equal)表示,
以示与无符号数条件转移指令的区别,见表 5— 3,表中 A,B为两个符号数。
表 5— 3符号数条件转移指令
【 例 5— 4】 JG与 JA指令。
MOV AL,一 40H
CMP AL,50H
JG LLL; AL<50H,顺序执行,不转移
JA LLL;用 AL的补码进行比较,条件成立,转 LLL处继续执行
5,CX条件转移指令
( 1) CX条件转移指令 JCXZ是一条特殊的条件转移指令,它以
CX的内容作为转移的条件,CX为 0时转移,CX非 0时不转移。
( 2)使用 CX条件转移指令前必须初始化 CX。
( 3)当 CX用作计数器时,JCXZ指令对程序设计很有帮助。
( 4) JCXZ指令等价于:
CMP CX,O
JZ 短标号第 4节 分支程序设计方法一,两路分支程序设计方法
( 1)两路分支程序是一种最简单的分支程序,根据程序中给出的一个条件,判定其是否满足,从而确定是否要执行某种操作。产生这种结构的分支一般要有,产生条件,,
,测试,,,定向,和,标号,4个组成部分。
( 2)通常通过算术运算指令和移位指令的运算结果影响标志寄存器的状态标志位,如 ZF,CF、
OF,SF等,为测试条件做准备;再用逻辑运算指令 (如
AND,TEST等 )进行测试;然后根据测试结果,确定程序的转移方向,转移地址用标号标识。
【 例 5— 5】 用逻辑指令和条件转移指令实现两路分支的程序段。
MOVAX,x:假定 x为字变量
ORAX,AX; AX置 0,影响标志位,准备转移条件
JZ NEXT; ZF=I转移到标号 NEXT处执行
……,分支处理 2
JMP DONE;段内直接转标号 DONE处执行,退出分支处理
NEXT,……,分支处理 1
DONE,RET
二,多路分支程序设计方法多路分支程序设计常用的方法有两种。
( 1)一种是组合条件法,相应于二叉树型数据结构来组织处理,也就是通过两路分支的嵌套,
由多条条件转移指令的组合来实现。由于需逐一比较,当条件转移指令较多时这种方法显得非常繁琐,尤其是进入不同叉的等待时间不等,进入最后叉的等待时间最长,这对于那些要求进入各个叉的等待时间相同,执行时间又尽可能短的问题是无能为力的。
适合在分支不多的情况下使用。
( 2)二是跳转表法,通过简单的运算将转移条件与转移地址或转移指令联系起来,这样无需用比较语句来实现分支程序的转移,在 BIOS及 DOS系统程序中大量采用跳转表实现各种例程。
跳转表法是多路分支程序设计较为理想的方法。
1.组合条件法一次判断转移可形成两路分支,以次判断转移便可以形成 n+l路分支。
【 例 5— 8】 编写程序,计算 y,其中一 128qRl27。
y=
1 X>O
0 X,O
本例是一个典型的三路分支处理程序,程序如下:
DATA SE(,JMEN。 I’
X DB?
Y DB?
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA,SS,STACK
MAINPROCFAR
PUSH DS
MOV AX,0
PUSH AX;保存 PSP地址,另一种方式返回 DOS
MOV AX,DATA
MOV DS,AX
MOV AL,X
CMP AL,O:准备转移条件
JZ ZERO;为 0时转 ZERO处
JSNEGL;为负时转 NEGL处
MOV AL,1:为正时等于 1
JMPDONE
NEGL,MOV AL,0FFH;为负时等于一 1
JMPDONE
ZERO,MOV AL,O:为 0时等于 0
DONE,MOV Y,AL;计算结果送 Y
RET=返回
MAIN ENDP
CODE ENDS
END MAIN
2.跳转表法跳转表法实现多路分支程序设计的核心思想是:在内存中开辟一片连续存储单元作为跳转表,表中顺序存放着进入各个分支处理程序的转移地址或转移指令。需要进入某分支的处理程序,只需查找跳转表中对应分支的地址或指令相应位置即可。
跳转表法又分为地址跳转表法和指令跳转表法。
(1)地址跳转表法在地址跳转表法中,跳转表存放各个分支的转移地址,跳转表可以通过
Dw伪指令来定义。
( 2)指令跳转表法在指令跳转表法中,跳转表直接存放各个分支处理的转移指令,跳转表在代码段中定义。
三,对于分支程序设计,归纳一下,有这样几点务必注意:
(1)选择合适的转移指令,否则可能不能转移到预定的程序分支。
(2)必须为每个分支安排出口,否则将导致程序运行混乱。
(3)应把各分支中的公共部分尽可能集中到分支前或后的程序段中。
(4)程序中分支出现顺序必须与流程图中一致,也尽量与问题中一致。
(5)在调试程序时,应尽可能对每个分支进行测试。
(6)无条件转移指令的转移范围不受限制,条件转移指令只能在 _128~
127字节范围内转移。
第 5节,分支程序设计举例
1.【 例 5一 ll】 编写程序,将三个符号数的最大者送入 MAX字单元。
三个符号数用 x,Y,Z描述,最大值用 MAX表示。
程序流程图如图 5— 5所示。
程序如下:
DAI,A SEGMENT
X DW 1234H
Y DW 4321H
Z DW 3421H
M_AX DW?
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA,SS,STACK
BEGIN,MOV AX,DATA
MOV DS,AX
MOV AX,X
CMP’AX,Y,X>Y?
JGXGZ
MOV AX,Y
CMP AX,Z,Y>Z?
JGNEXT
ZTO AX,MOV AX,Z
JMP NEXT
XGZ,CMPAX,Z,X>Z?
JNG ZTOAX
NEXT,MOV MAX,AX
MOV AH,4CH
INT21H
CODE ENDS
END BEGIN
2.【 例 5— 12】 编写程序,将输入的大写字母转换为小写字母。英文大、
小写字母的 ASCII码相差为 20H,将大写字母转换为相应的小写字母,只需将大写字母的 ASCII码加上 20H即可。
用 01号功能调用实现从键盘输入一个字符,用 02号功能调用输出一个小写字母,用 09号功能显示出错信息,用 CMP和 JMB指令实现分支程序设计。假定输入以,#”结束。
程序流程图如图 5— 6所示。
程序如下:
DATA SEGMENT
ERRMESS DB’ERROR!’,’ $’
DATA ENDS
STACK SEGMENT STACK 图 5— 6 例 5一 12程序流程图
DB 100DUP(?)
STACK ENDS
CODE SEGMENT
ASSI,ME CS,CODE,DS,DATA,SS,S1,ACK
START,MOV AX,DATA
MOV DS,AX
LLL,MOV AH,1:从键盘输入一个字符送 AL
INT21H
cMP AL,’ #’;输入字符为 ’ #’结束
JZDONE
CMP AL,’ A’;若不是大写字母,转显示出错信息
JB ERR
CMAL,’ Z’
JAERR
ADD AL,20H;转换成小写字母
MOV DL,AL:输出
MOV AH,2
INT 2lH
JMP LLL:继续输入
ERR,MoV Dx,OFFSET ERRM[ESS:输出出错信息
MOV AH,9
INT 21H
JMPLLL
DONE,MOV AH,4CH
INT 21H
CoDE ENDS
END START
3.【 例 5— 13】 对例 4~ 28计算 0~ 9中数的立方程序进行改进,增加容错处理。
程序流程图如图 5— 7所示。
程序如下:
STACK SEGMENT S1tACK
DW】 OOHDIm(O)
STACK ENDS
DATA SEGMENT
MESS DB’INPUT X(0~ 9),$’
TAB DW 0,1,8,27,64,125
X DB?
DAI’A
CODE
MAIN:
图 5— 7例 5— 13程序流程图
216,343,512,729:定义数据表
XXX DW?
ERR DB ’INPUT ERROR!$’
ENDS
SEGMENT
ASSUME CS,CoDE,DS,DAIA,SS,STACK
MOV AX,DATA
MOV DS,AX
MOV Dx,OFFSET MESS:显示提示信息
MOV AH,9
INT2lH
MOVAH,1:输入 X
INT21H
CMP AL,’ O’:改进部分
JB LERR ’
CMP AL,’ 9’
JALERR
AND AL,OFH,AScII码转换成真值
MOV X,AL
ADD AL,AL:计算表中 16位位移
MOV BL,AL
MOV BH,O:
MOV AX,TAB[Bx]; [TAB+Bx】 为所求立方值的偏移地址
MOVXXX,AX
EXIT,MOV AH,4CH
INT 21H
LERR,MOv DX,0FFSET ERR;输出出错信息
MoV AH,9
INT21H
JMPEⅪ T
CODE ENDS
ENDMAIN