循環(huán)程序可以有兩種結(jié)構(gòu)形式,如圖所示。一種是do_while結(jié)構(gòu)形式;另一種是do_until結(jié)構(gòu)形式。
例5.1設(shè)內(nèi)存buff開始的單元中依次存放著30個(gè)8位無符號(hào)數(shù),求它們的和并放在sum單元中,試編寫程序。
分析:這是一個(gè)求累加的程序。程序如下:
movsi,buff;設(shè)地址指針
mov cx,30;設(shè)計(jì)數(shù)初值
xor ax,ax??;設(shè)累加器初值
again: add al,[si]
adc ah,0
incsi
dec cx
jnzagain?。谎h(huán)累加
mov sum,ax
例5.2在給定個(gè)數(shù)的16位數(shù)串中,找出大于零、等于零和小于零的個(gè)數(shù),并緊跟著原串存放。
分析:這是一個(gè)統(tǒng)計(jì)問題,須設(shè)定三個(gè)計(jì)數(shù)器分別統(tǒng)計(jì)三種情況下的結(jié)果。程序如下:
data segment
buff dwx1,x2,x3,……,xn
countequ$-buff ;此時(shí),count的值為buff所占的字節(jié)數(shù)
plusedb ?
zero db???
minus db???
data ends
code segment
assume cs:code,ds:data
assume es:data,ss:stack
begin: mov ax,data
mov ds,ax
mov cx,count
shr cx,1??;相當(dāng)于除2,正好為buff中的數(shù)據(jù)個(gè)數(shù)
mov dx,0;設(shè)定計(jì)數(shù)器初值
mov ax,0;設(shè)定計(jì)數(shù)器初值
leabx,buff
again: cmpword ptr[bx],0
jaeplu;大于等于0,則轉(zhuǎn)piu
incah??;<0,則統(tǒng)計(jì)
jmpnext
plu: jzzer ;=0,則轉(zhuǎn)zer
incdl;>0,則統(tǒng)計(jì)
jmpnext
zer:incdh;=0,則統(tǒng)計(jì)
next:incbx
incbx
loop again
mov plus,dl
mov zero,dh
mov minus,ah
mov ax,4c00h
int21h
codeends
end begin
例5.3 在addr單元中存放著16位數(shù)y的地址,試編寫一程序,把y中1的個(gè)數(shù)存入count單元中。
分析:這是一個(gè)循環(huán)統(tǒng)計(jì)的工作。采用do—while結(jié)構(gòu),做16次循環(huán),每次將最高位移入cf中進(jìn)行測試,先判斷結(jié)果是否為0,若為0,則結(jié)束;否則統(tǒng)計(jì)計(jì)數(shù)后循環(huán)重復(fù)。
程序如下:
data segment
addr dwnumber
number dwy
countdw?
dataends
program segment
mainproc far
assume cs:program,ds:data
start: push ds
mov ax,0
push ax
mov ax,data
mov ds,ax
mov cx,0?。挥?jì)數(shù)器初值=0
mov bx,addr
mov ax,[bx]??;取y送ax
repeat: test ax,0ffffh;檢測是否為全0
jzexit?。皇?,則轉(zhuǎn)exit
jnsshift;最高位是0,則轉(zhuǎn)shift
inccx??;最高位是1,則統(tǒng)計(jì)計(jì)數(shù)
shift:shlax,1??;處理下一位
jmprepeat
exit:mov count,cx
ret
mainendp
program ends
end start
在實(shí)際應(yīng)用中,有些問題較復(fù)雜,一重循環(huán)不夠,必須使用多重循環(huán)實(shí)現(xiàn),這些循環(huán)是一層套一層的,通常稱為循環(huán)嵌套。
例5.4 在ds所決定的數(shù)據(jù)段,從偏移地址buffer開始順序存放100個(gè)無符號(hào)16位數(shù),現(xiàn)要編寫程序?qū)⑦@100個(gè)字?jǐn)?shù)據(jù)從大到小排序。
分析:排序的方法有很多,在這里,我們采用冒泡法。
程序如下:
leadi,buffer ;di作為指針,指向要排序的數(shù)據(jù)
mov bl,99??;循環(huán)控制初值
next0:mov si,di
mov cl,bl
next3:mov ax,[si];取一個(gè)數(shù)
add si,2
cmp ax,[si];與下一個(gè)數(shù)進(jìn)行比較
jncnext5;大于等于時(shí)轉(zhuǎn)移
mov dx,[si];否則,兩數(shù)交換
mov [si-2],dx
mov [si],ax
next5:dec cl?。豢刂七M(jìn)行交換的次數(shù)
jnznext3
dec bl?。恍薷慕粨Q的次數(shù)
jnznext0
hlt
例5.5試編制一個(gè)程序,把bx寄存器中的二進(jìn)制數(shù)以十六進(jìn)制的形式顯示在屏幕上。
解析:根據(jù)題目要求應(yīng)將bx中的內(nèi)容從左到右每4位一組顯示出來,共顯示4個(gè)十六進(jìn)制數(shù)位。如果顯示的數(shù)位是0~9,則把4位二進(jìn)制數(shù)加上30h,轉(zhuǎn)換成相應(yīng)的ascii碼30h~39h;如果是a~f,則應(yīng)加上37h(30h+7),轉(zhuǎn)換成ascii碼41h~46h。顯示字符可以使用dos功能調(diào)用來實(shí)現(xiàn)。下圖是程序框圖。
以binihex.a(chǎn)sm為文件名,建立源程序如下:
; binihex.a(chǎn)sm
prognam segment ; 定義代碼段
main proc far
assume cs:prognam
start:; 程序從此處開始執(zhí)行
; 為正常返回dos而設(shè)置堆棧
pushds
sub ax,ax
pushax
; 下面是程序的主要部分
movch,4 ; 4組二進(jìn)制數(shù)
rotate:
movcl,4; 每組4個(gè)二進(jìn)制位
rolbx,cl; 把bx循環(huán)左移4位
moval,bl; 暫存bl到al中
andal,0fh; 僅保留al的低4位
addal,30h ; 轉(zhuǎn)換成ascii碼
cmpal,3ah ; 要顯示的數(shù)大于9 ?
jl printit ; 如果數(shù)在0~9之間則顯示
addal,7h; 數(shù)在a~f之間則調(diào)整
printit:
movdl,al; 把要顯示字符的ascii碼送dl
movah,2 ; 功能號(hào)2送ah
int21h ; dos功能調(diào)用
decch; (ch)-1
jnzrotate; 4組都處理完?否,循環(huán)處理下一組
ret; 返回dos
main endp; 主程序main結(jié)束
prognamends; 代碼段結(jié)束
endstart; 結(jié)束匯編
例5.6 從鍵盤接收十進(jìn)制數(shù)并存入 bx
prognam segment
main proc far
assume cs:prognam
start:
push ds
subax,ax
push ax
mov bx, 0
newchar:
mov ah, 1;鍵盤輸入
int 21h
sub al, 30h
jl exit;<0退出
cmp al, 9
jg exit;>9退出
cbw
例5.7 從鍵盤接收十六進(jìn)制數(shù)并存入 bx
codesegment
assume cs:code, ds:data
start:
mov ax,4c00h
int 21h; 返回dos
codeends
endstart
例5.8 將正數(shù)n插入一個(gè)已整序的字?jǐn)?shù)組的正確位置。該數(shù)組的首地址和末地址分別為array_head和array_end,其中所有數(shù)均為正數(shù)且已按遞增的次序排列。
; 定義數(shù)據(jù)段
datarea segment
xdw?
array_headdw23,37,49,52,65,78,99
array_enddw105
n dw32
datarea ends
; 定義代碼段
prognam segment
mainprocfar; 主程序部分 assume cs:prognam,ds:datarea
start: ; 程序從此處開始執(zhí)行
pushds
subax,ax
pushax
movax,datare