分支程序设计
(1)简单分支程序:通过判断一个条件获得两路分支,该条件的判断结果决定了程序的执行流向。缺点在于执行流向的局限性,例如当条件为一个多分段函数时,则无法满足要求。
实例:试编程实现函数Y=MAX(X1、X2、X3)的程序。程序流程图如图所示(设X1、X2、X3存放在以BUF起始的3个连续单元中,且均为无符号的8位二进制数)
.486
DATA SEGMENT
BUF DB 21,30,98
Y DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
LEA SI,BUF
MOV AL,[SI]
CMP AL,[SI+1]
JNB NEXT ;如果X1不小于X2,则转到NEXT
MOV AL,[SI+1] ;如果X1小于X2,则将A2送给AL
NEXT: CMP AL,[SI+2]
JNB NEXT1
MOV AL,[SI+2]
NEXT1: MOV Y,AL
MOV AH,4CH
INT 21H
CODE ENDS
END START
(2)多分支程序:为解决单分支结构程序的缺点,采用跳转表法实现多分支程序的设计。例如如果我们想要设计一个4分支的程序,在数据段中定义一个TBLE跳转表,里面分别存放4个CASE的地址。每个地址占内存两个单元(2个字节),那么CASE0的地址存放在数据段中地址为TBLE的地方,即表首。假设满足CASE0时跳转至CS段地址为122AH的地方,那么TABLE存放2AH,TABLE+1存放12H。
跳转表地址 | 入口标号地址 | 序号 |
---|---|---|
TBLE | R0低字节+R0高字节 | 0 |
TBLE+2 | R1低字节+R1高字节 | 1 |
TBLE+4 | R2低字节+R2高字节 | 2 |
TBLE+8 | R3低字节+R3高字节 | 4 |
实例:试编程实现:在提示字符串“INPUT”后输入数字序号0~4,根据键盘输入的数字转向5个分支程序段中的某一个。假设各分支程序段入口地址标号为R0-R4,若输入数字n则准信Rn程序段并显示“OUTPUT:n”。当按下回车键时,结束程序。要求利用跳转表实现转移(设各分支程序段与主程序在同一段代码中)。
.486
DATA SEGMENT
TBLE DW R0,R1,R2,R3,R4 ;自动将Rx的偏移地址填进去
MESS1 DB 'INPUT:$' ; 字符串定义时必须以'$'结尾
MESS2 DB 'OUTPUT:$'
DATA ENDS
STACKA SEGMENT PARA STACK'STACK' ;PARA定义段首地址(20位的后4位0)为16的整数倍
DW 50 DUP(?)
STACKA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACKA
MAIN PROC FAR ;子程序定义指令PROC,FAR为段间调用
START: PUSH DS
MOV AX,0
PUSH AX ;将子程序中将会用到的寄存器中的内容压栈
MOV AX,DATA
MOV DS,AX
MOV AX,STACKA
MOV SS,AX ;16~19段寄存器说明语句
AGAN: LEA DX,MESS1
MOV AH,09H
INT 21H ; DOS09号功能调用
MOV AH,01H
INT 21H ;DOS01号功能调用
CMP AL,0DH; 是否键入回车,回车符的ascii码为0DH
JZ EXIT
CMP AL,'4'
JA AGAN
AND AL,0FH ;将ascii码变为数字,0~9对应十六进制ascii30~39
MOVZX AX,AL
SHL AX,1
MOV SI,AX
LEA DX,MESS2
MOV AH,9
INT 21H
JMP TBLE[SI] ;转向键入序号程序段,寄存器相对寻址方式
R0: MOV DL,'0'
JMP DISP
R1: MOV DL,'1'
JMP DISP
R2: MOV DL,'2'
JMP DISP
R3: MOV DL,'3'
JMP DISP
R4: MOV DL,'4'
JMP DISP
DISP: MOV AH,02H
INT 21H ;
JMP AGAN
EXIT: RET
MAIN ENDP
CODE ENDS
END START
注:在DOS的01H,02H,09H功能中,程序中输入输出都为字符相应的ASCII码,而不是直接的数。