分支程序的基本思想是根据逻辑判断的结果来形成程序的分支,如图,若A成立,则执行P1;否则执行P2。
分支程序有两种基本结构,如图所示。
它们分别相当于高级语言中的IF_THEN_ELSE语句和CASE语句,适用于要求根据不同条件作不同处理的情况。IF_THEN_ELSE语句可以引出两个分支,CASE语句则可以引出多个分支,不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。
例1 试编写程序段,实现符号函数。 分析:变量X的符号函数可表示为: 程序可通过对符号标志的判别来确定执行哪一分支。 START: MOV AX,BUFFER ;(BUFFER)=X OR AX,AX JE ZERO ;X=0,则转ZERO JNS PLUS ;X为正数,则转PLUS MOV BX,0FFFFH ;X为负数,则-1送BX JMP CONT1 ZERO: MOV BX,0 JMP CONT1 PLUS: MOV BX,1 CONT1: …… 例2 利用表实现分支。根据AL中各位被置位情况,控制转移到8个子程序P1~P8之一中去。转移表的结构如表1所示。 分析:对于这种程序关键要找出每种情况的转移地址,从图中可见表地址=表基地址+偏移量, 而偏移量可由AL各位所在位置*2求得。
DATA SEGMENT BASE DW SR0,SR1,SR2,SR3, SR4,SR5,SR6,SR7 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA BEGIN: PUSH DS XOR AX,AX PUSH AX MOV AX,DATA MOV DS,AX LEA BX,BASE ;表头送BX IN AL,PORT GETBIT: RCR AL,1 ;右移一位 JC GETAD ;移出位是1? INC BX INC BX ;修改指针 JMP GETBI GETAD: JMP WORD PTR[BX] ;实现散转 CODE ENDS END BEGIN 例3 将内存中某一区域的原数据块传送到另一区域中。 分析:这种程序若源数据块与目的数据块之间地址没有重叠,则可直接用传送或串操作实现;若地址重叠,则要先判断源地址+数据块长度是否小于目的地址,若是,则可按增量方式进行,否则要修改指针指向数据块底部,采用减量方式传送。程序如下: DATA SEGMENT STR DB 1000DUP(?) STR1 EQU STR+7 STR2 EQU STR+25 STRCOUNT EQU 50 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ STAPN DB 100DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK GOO PROC PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV AX,STACK MOV SS,AX MOV CX,STRCOUNT MOV SI,STR1 MOV DI,STR2 CLD PUSH SI ADD SI,STRCOUNT-1 CMP SI,DI POP SI JL OK STD ADD SI,STRCOUNT-1 ADD DI,STRCOUNT-1 OK: REP MOVSB RET GOO ENDP CODE ENDS END GOO
cseg segment main proc near assume cs:cseg, ds:data start: mov ax,dseg mov ds,ax
exit: mov ax,4c00h int 21h main endp cseg ends end start 例4 试根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支中去。 branch_addresses segment ; 定义数据段 branch_table dw routine_1 dw routine_2 dw routine_3 dw routine_4 dw routine_5 dw routine_6 dw routine_7 dw routine_8 branch_addresses ends procedure_select segment ; 定义代码段 main proc far ; 定义主程序main assume cs:procedure_select,ds:branch_addresses start: push ds sub bx,bx push bx mov bx,branch_addresses mov ds,bx ; 程序的主要部分(寄存器相对寻址) cmp al,0 ; (al)=0? je continue ; (al)为0则转到continue_main_line mov si,0 l: shr al,1 ; 把al逻辑右移1位 jnc not_yet ; CF=0转到not_yet jmp branch_table[si] ; CF=1转到相应程序分支 not_yet: add si,type branch_table ; 修改地址add si,2 jmp l ; 无条件跳到l continue: ; 其它程序段 … routine_1: … ; 程序段1 routine_2: … ; 程序段2 ret main endp ; 主程序main结束 procedure_select ends end start 用寄存器间接寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分): …… cmp al,0 je continue lea bx,branch_table ; branch_table的偏移地址送bx l: shr al,1 jnc not_yet ; CF=0转到not_yet jmp word ptr[bx] ; CF=1转到相应程序分支 not_yet: add bx,type branch_table ; 修改地址 jmp l ; 无条件跳到l continue: …… 用基址变址寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分),与前两种寻址方式的主要区别是这里使用了逻辑左移指令,即从al的高位向低位判断,而前两段程序是从al的低位向高位判断。 …… cmp al,0 je continue lea bx,branch_table mov si,7*type branch_table ; 14送si mov cx,8 ; 循环次数8送cx l: shl al,1 ; 把al逻辑左移1位 jnb not_yet ; CF=0转到not_yet jmp word ptr[bx][si] ; CF=1转到相应程序分支 not_yet: sub si,type branch_table ; 修改地址 loop l ; 循环 continue: …… 以上多个例子都是既有分支结构又有循环结构,实际上,多数程序都是各种程序结构的组合。而且,循环结构可以看作分支结构的一种特例,它只是多次走一个分支,只在满足循环结束条件时,走另一个分支罢了。 算法和循环控制条件的选择对程序的工作效率有很大的影响,而循环控制条件的选择又是很灵活的,应该根据具体情况来确定。考虑算法时必须把可能出现的边界情况考虑在内。 设置逻辑尺是循环控制中很常用的一种方法。除了静态地预置外,还可以在程序中动态地修改标志位的值,以达到控制的目的。 循环可以有多层结构。多重循环程序设计的基本方法和单重循环程序设计是一致的,应分别考虑各重循环的控制条件及其程序实现,相互之间不能混淆。另外,应该注意在每次通过外层循环再次进入内层循环时,初始条件必须重新设置。 起泡排序算法是多重循环程序设计中的一种常用方法。 分支程序结构可以有两种形式。分别相当于高级语言中的IF_THEN_ELSE语句和CASE语句,适用于要求根据不同条件作不同处理的情况。 IF_THEN_ELSE语句可以引出两个分支,CASE语句则可以引出多个分支,不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。 数组排序算法中可以采用折半查找法来提高查找效率。 CASE结构可以使用跳跃表法实现,使程序能根据不同的条件转移到多个程序分支中去。跳跃表法;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;是一种很有用的分支程序设计方法。 |
电工学习网 ( )
GMT+8, 2021-12-6 20:45