您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

分支程序设计

2024/10/23 12:03:56发布46次查看
分支程序的基本思想是根据逻辑判断的结果来形成程序的分支,如图,若a成立,则执行p1;否则执行p2。 分支程序有两种基本结构,如图所示。
它们分别相当于高级语言中的if_then_else语句和case语句,适用于要求根据不同条件作不同处理的情况。if_then_else语句可以引出两个分支,case语句则可以引出多个分支,不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。
例1试编写程序段,实现符号函数。
分析:变量x的符号函数可表示为:
程序可通过对符号标志的判别来确定执行哪一分支。
start: mov ax,buffer;(buffer)=x
orax,ax
jezero ;x=0,则转zero
jnsplus;x为正数,则转plus
mov bx,0ffffh ;x为负数,则-1送bx
jmpcont1
zero:mov bx,0
jmpcont1
plus:mov bx,1
cont1: ……
例2利用表实现分支。根据al中各位被置位情况,控制转移到8个子程序p1~p8之一中去。转移表的结构如表1所示。
分析:对于这种程序关键要找出每种情况的转移地址,从图中可见表地址=表基地址+偏移量, 而偏移量可由al各位所在位置*2求得。
表1 子程序r1—r8的入口地址表
p1
子程序r1的入口偏移地址
p2
子程序r2的入口偏移地址
p3
子程序r3的入口偏移地址
……
……
…….
……
p7
子程序r7的入口偏移地址
p8
子程序r8的入口偏移地址
datasegment
basedwsr0,sr1,sr2,sr3, 
sr4,sr5,sr6,sr7
dataends
codesegment
assume cs:code,ds:data,es:data
begin:push ds
xor ax,ax
pushax
mov ax,data 
mov ds,ax
lea bx,base ;表头送bx
inal,port 
getbit: rcr al,1;右移一位
jcgetad;移出位是1?
incbx
inc bx ;修改指针
jmpgetbi
getad: jmpword ptr[bx] ;实现散转
codeends
endbegin
例3将内存中某一区域的原数据块传送到另一区域中。
分析:这种程序若源数据块与目的数据块之间地址没有重叠,则可直接用传送或串操作实现;若地址重叠,则要先判断源地址+数据块长度是否小于目的地址,若是,则可按增量方式进行,否则要修改指针指向数据块底部,采用减量方式传送。程序如下:
datasegment
str db 1000dup(?)
str1equ str+7
str2equ str+25
strcount equ 50
dataends
stacksegment parastack‘stack’
stapndb100dup(?)
stackends
codesegment
assume cs:code,ds:data,es:data,ss:stack
goo proc
push ds
subax,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
popsi
jlok
std
add si,strcount-1
add di,strcount-1
ok:repmovsb
ret
gooendp
codeends
end goo
csegsegment
main procnear
assume cs:cseg, ds:data
start:
movax,dseg
movds,ax
exit:movax,4c00h
int21h
mainendp
csegends
endstart
例4 试根据al寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支中去。
branch_addressessegment; 定义数据段
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_addressesends
procedure_selectsegment; 定义代码段
main procfar; 定义主程序main
assume cs:procedure_select,ds:branch_addresses
start: 
pushds 
sub bx,bx 
pushbx 
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 
mainendp ; 主程序main结束
procedure_select ends 
end start
用寄存器间接寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分):
……
cmpal,0 
je continue 
leabx,branch_table ; branch_table的偏移地址送bx l: shral,1 
jncnot_yet ; cf=0转到not_yet
jmpword ptr[bx] ; cf=1转到相应程序分支
not_yet: addbx,type branch_table ; 修改地址
jmpl; 无条件跳到l
continue: 
…… 
用基址变址寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分),与前两种寻址方式的主要区别是这里使用了逻辑左移指令,即从al的高位向低位判断,而前两段程序是从al的低位向高位判断。
……
cmpal,0 
je continue
leabx,branch_table 
movsi,7*type branch_table ; 14送si
movcx,8; 循环次数8送cx
l: shlal,1; 把al逻辑左移1位
jnbnot_yet ; cf=0转到not_yet
jmpword ptr[bx][si]; cf=1转到相应程序分支
not_yet: subsi,type branch_table; 修改地址
loop l; 循环
continue: 
……
以上多个例子都是既有分支结构又有循环结构,实际上,多数程序都是各种程序结构的组合。而且,循环结构可以看作分支结构的一种特例,它只是多次走一个分支,只在满足循环结束条件时,走另一个分支罢了。
算法和循环控制条件的选择对程序的工作效率有很大的影响,而循环控制条件的选择又是很灵活的,应该根据具体情况来确定。考虑算法时必须把可能出现的边界情况考虑在内。
设置逻辑尺是循环控制中很常用的一种方法。除了静态地预置外,还可以在程序中动态地修改标志位的值,以达到控制的目的。
循环可以有多层结构。多重循环程序设计的基本方法和单重循环程序设计是一致的,应分别考虑各重循环的控制条件及其程序实现,相互之间不能混淆。另外,应该注意在每次通过外层循环再次进入内层循环时,初始条件必须重新设置。
起泡排序算法是多重循环程序设计中的一种常用方法。
分支程序结构可以有两种形式。分别相当于高级语言中的if_then_else语句和case语句,适用于要求根据不同条件作不同处理的情况。
if_then_else语句可以引出两个分支,case语句则可以引出多个分支,不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。
数组排序算法中可以采用折半查找法来提高查找效率。
case结构可以使用跳跃表法实现,使程序能根据不同的条件转移到多个程序分支中去。跳跃表法;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;是一种很有用的分支程序设计方法。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product