分支程序的基本思想是根據(jù)邏輯判斷的結(jié)果來(lái)形成程序的分支,如圖,若a成立,則執(zhí)行p1;否則執(zhí)行p2。
分支程序有兩種基本結(jié)構(gòu),如圖所示。
它們分別相當(dāng)于高級(jí)語(yǔ)言中的if_then_else語(yǔ)句和case語(yǔ)句,適用于要求根據(jù)不同條件作不同處理的情況。if_then_else語(yǔ)句可以引出兩個(gè)分支,case語(yǔ)句則可以引出多個(gè)分支,不論哪一種形式,它們的共同特點(diǎn)是:運(yùn)行方向是向前的,在某一種特定條件下,只能執(zhí)行多個(gè)分支中的一個(gè)分支。
例1試編寫(xiě)程序段,實(shí)現(xiàn)符號(hào)函數(shù)。
分析:變量x的符號(hào)函數(shù)可表示為:
程序可通過(guò)對(duì)符號(hào)標(biāo)志的判別來(lái)確定執(zhí)行哪一分支。
start: mov ax,buffer;(buffer)=x
orax,ax
jezero?。粁=0,則轉(zhuǎn)zero
jnsplus;x為正數(shù),則轉(zhuǎn)plus
mov bx,0ffffh?。粁為負(fù)數(shù),則-1送bx
jmpcont1
zero:mov bx,0
jmpcont1
plus:mov bx,1
cont1: ……
例2利用表實(shí)現(xiàn)分支。根據(jù)al中各位被置位情況,控制轉(zhuǎn)移到8個(gè)子程序p1~p8之一中去。轉(zhuǎn)移表的結(jié)構(gòu)如表1所示。
分析:對(duì)于這種程序關(guān)鍵要找出每種情況的轉(zhuǎn)移地址,從圖中可見(jiàn)表地址=表基地址+偏移量, 而偏移量可由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]??;實(shí)現(xiàn)散轉(zhuǎn)
codeends
endbegin
例3將內(nèi)存中某一區(qū)域的原數(shù)據(jù)塊傳送到另一區(qū)域中。
分析:這種程序若源數(shù)據(jù)塊與目的數(shù)據(jù)塊之間地址沒(méi)有重疊,則可直接用傳送或串操作實(shí)現(xiàn);若地址重疊,則要先判斷源地址+數(shù)據(jù)塊長(zhǎng)度是否小于目的地址,若是,則可按增量方式進(jìn)行,否則要修改指針指向數(shù)據(jù)塊底部,采用減量方式傳送。程序如下:
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 試根據(jù)al寄存器中哪一位為1(從低位到高位)把程序轉(zhuǎn)移到8個(gè)不同的程序分支中去。
branch_addressessegment; 定義數(shù)據(jù)段
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
; 程序的主要部分(寄存器相對(duì)尋址)
cmp al,0 ; (al)=0?
je continue ; (al)為0則轉(zhuǎn)到continue_main_line
mov si,0
l:shr al,1; 把a(bǔ)l邏輯右移1位
jnc not_yet ; cf=0轉(zhuǎn)到not_yet
jmp branch_table[si] ; cf=1轉(zhuǎn)到相應(yīng)程序分支
not_yet: add si,type branch_table; 修改地址add si,2
jmp l; 無(wú)條件跳到l
continue:; 其它程序段
…
routine_1:
… ; 程序段1
routine_2:
… ; 程序段2
ret
mainendp ; 主程序main結(jié)束
procedure_select ends
end start
用寄存器間接尋址方式實(shí)現(xiàn)跳躍表法的程序如下(僅給出修改后的程序的主要部分):
……
cmpal,0
je continue
leabx,branch_table ; branch_table的偏移地址送bx l: shral,1
jncnot_yet ; cf=0轉(zhuǎn)到not_yet
jmpword ptr[bx] ; cf=1轉(zhuǎn)到相應(yīng)程序分支
not_yet: addbx,type branch_table ; 修改地址
jmpl; 無(wú)條件跳到l
continue:
……
用基址變址尋址方式實(shí)現(xiàn)跳躍表法的程序如下(僅給出修改后的程序的主要部分),與前兩種尋址方式的主要區(qū)別是這里使用了邏輯左移指令,即從al的高位向低位判斷,而前兩段程序是從al的低位向高位判斷。
……
cmpal,0
je continue
leabx,branch_table
movsi,7*type branch_table ; 14送si
movcx,8; 循環(huán)次數(shù)8送cx
l: shlal,1; 把a(bǔ)l邏輯左移1位
jnbnot_yet ; cf=0轉(zhuǎn)到not_yet
jmpword ptr[bx][si]; cf=1轉(zhuǎn)到相應(yīng)程序分支
not_yet: subsi,type branch_table; 修改地址
loop l; 循環(huán)
continue:
……
以上多個(gè)例子都是既有分支結(jié)構(gòu)又有循環(huán)結(jié)構(gòu),實(shí)際上,多數(shù)程序都是各種程序結(jié)構(gòu)的組合。而且,循環(huán)結(jié)構(gòu)可以看作分支結(jié)構(gòu)的一種特例,它只是多次走一個(gè)分支,只在滿足循環(huán)結(jié)束條件時(shí),走另一個(gè)分支罷了。
算法和循環(huán)控制條件的選擇對(duì)程序的工作效率有很大的影響,而循環(huán)控制條件的選擇又是很靈活的,應(yīng)該根據(jù)具體情況來(lái)確定??紤]算法時(shí)必須把可能出現(xiàn)的邊界情況考慮在內(nèi)。
設(shè)置邏輯尺是循環(huán)控制中很常用的一種方法。除了靜態(tài)地預(yù)置外,還可以在程序中動(dòng)態(tài)地修改標(biāo)志位的值,以達(dá)到控制的目的。
循環(huán)可以有多層結(jié)構(gòu)。多重循環(huán)程序設(shè)計(jì)的基本方法和單重循環(huán)程序設(shè)計(jì)是一致的,應(yīng)分別考慮各重循環(huán)的控制條件及其程序?qū)崿F(xiàn),相互之間不能混淆。另外,應(yīng)該注意在每次通過(guò)外層循環(huán)再次進(jìn)入內(nèi)層循環(huán)時(shí),初始條件必須重新設(shè)置。
起泡排序算法是多重循環(huán)程序設(shè)計(jì)中的一種常用方法。
分支程序結(jié)構(gòu)可以有兩種形式。分別相當(dāng)于高級(jí)語(yǔ)言中的if_then_else語(yǔ)句和case語(yǔ)句,適用于要求根據(jù)不同條件作不同處理的情況。
if_then_else語(yǔ)句可以引出兩個(gè)分支,case語(yǔ)句則可以引出多個(gè)分支,不論哪一種形式,它們的共同特點(diǎn)是:運(yùn)行方向是向前的,在某一種特定條件下,只能執(zhí)行多個(gè)分支中的一個(gè)分支。
數(shù)組排序算法中可以采用折半查找法來(lái)提高查找效率。
case結(jié)構(gòu)可以使用跳躍表法實(shí)現(xiàn),使程序能根據(jù)不同的條件轉(zhuǎn)移到多個(gè)程序分支中去。跳躍表法;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;是一種很有用的分支程序設(shè)計(jì)方法。