強(qiáng)制 cpu 重復(fù)執(zhí)行同一指令集合的一種程序結(jié)構(gòu),它可以使許多重復(fù)性工作的程序大為簡(jiǎn)化。
循環(huán)結(jié)構(gòu)一般是根據(jù)某一條件判斷為真或假來(lái)確定是否重復(fù)執(zhí)行循環(huán)體,循環(huán)指令和轉(zhuǎn)移指令可以實(shí)現(xiàn)循環(huán)控制;還可以采用 masm 6.x 提供的循環(huán)控制偽指令實(shí)現(xiàn)
循環(huán)結(jié)構(gòu)
.model small
.stack
.data
sum dw ?
.code
.startup
xor ax,ax ; 被加數(shù) ax 清 0
mov cx,100
again: add ax,cx
; 從 100,99,...,2,1 倒序累加
loop again
mov sum,ax ; 將累加和送入指定單元
.exit 0
end
例 1 : 在內(nèi)存 40000h 開(kāi)始的順序 30 個(gè)單元中存放著 8 位無(wú)符號(hào)數(shù),若將它們的和放在 dx 中,其程序如下:
mov ax , 4000h
mov ds , ax
mov si , 0000h
mov cx , 30
xor ax , ax
goon : add al , [si]
adc : ah , 00h
inc si
dec cx
jnz goon
mov dx , ax
hlt
例 2 :在 ds 所決定的數(shù)據(jù)段,從偏移地址 buffer 開(kāi)始順序存放 100 個(gè)無(wú)符號(hào)的 16 位數(shù),現(xiàn)欲編程序?qū)?100 個(gè)字按大小順序排列:
lea di , buffer
mov bl , 99
next0 :
mov si , di
mov cl , bl
next3 :
mov ax , [di]
;第一個(gè)數(shù) -->ax
add si , 2
cmp ax , [si]
;第一個(gè)數(shù)同第二個(gè)數(shù)比較
jnc next5
;第一個(gè)數(shù) 第二個(gè)數(shù),轉(zhuǎn) next5
mov dx , [si]
;若第一個(gè)數(shù) < 第二個(gè)數(shù),第二個(gè)數(shù) --> dx
mov [di] , dx
; dx--> 第一個(gè)位置
mov [si] , ax
next5 :
dec cl
jnz next3
; cl 0
inc di
inc di
dec bl
jnz next0
hlt
例 3 . 求 1-100 的和
計(jì)數(shù)控制循環(huán)
, 循環(huán)次數(shù)固定
mov ah,1 ; 從鍵盤(pán)輸入一個(gè)字符
int 21h
mov bl,al ;bl ← al =字符的 ascii 碼
;dos 功能會(huì)改變 al 內(nèi)容,故字符 ascii 碼存入 bl
mov ah,2
mov dl,':' ; 顯示一個(gè)分號(hào),用于分隔
int 21h
mov cx,8 ;cx ← 8 (循環(huán)次數(shù))
again: shl bl,1 ; 左移進(jìn) cf ,從高位開(kāi)始顯示
mov dl,0 ;mov 指令不改變 cf
adc dl,30h ;dl ← 0 + 30h + cf
;cf 若是 0 ,則 dl ← '0' ;若是 1 ,則 dl ← '1'
mov ah,2
int 21h ; 顯示
loop again ;cx 減 1 ,如果 cx 未減至 0 ,則循環(huán)
例 4: 用二進(jìn)制顯示從鍵盤(pán)輸入的一個(gè)字符的 ascii 碼
mov bx,offset string
again: mov al,[bx] ; 取一個(gè)字符
or al,al ; 是否為結(jié)尾符 0
jz done ; 是,退出循環(huán)
cmp al,'a' ; 是否為大寫(xiě) a ~ z
jb next
cmp al,'z'
ja next
or al,20h
; 是,轉(zhuǎn)換為小寫(xiě)字母(使 d5=1 )
mov [bx],al ; 仍保存在原位置
next: inc bx
jmp again ; 繼續(xù)循環(huán)
done: .exit 0
例 5. 大小寫(xiě)
條件控制循環(huán) , 利用標(biāo)志退出
冒泡法
“冒泡法”是一種排序算法,不是最優(yōu)的算法,但它易于理解和實(shí)現(xiàn)
冒泡法從第一個(gè)元素開(kāi)始,依次對(duì)相鄰的兩個(gè)元素進(jìn)行比較,使前一個(gè)元素不大于后一個(gè)元素;將所有元素比較完之后,最大的元素排到了最后;然后,除掉最后一個(gè)元素之外的元素依上述方法再進(jìn)行比較,得到次大的元素排在后面;如此重復(fù),直至完成就實(shí)現(xiàn)元素從小到大的排序
這需要一個(gè)雙重循環(huán)程序結(jié)構(gòu)
冒泡法的排序過(guò)程
比較遍數(shù)
序號(hào) 數(shù) 1 2 3 4
1 32 32 16 15 8
2 85 16 15 8 15
3 16 15 8 16 16
4 5 8 32 32 32
5 18 85 85 85 85
mov cx,count ;cx ←數(shù)組元素個(gè)數(shù)
dec cx ; 元素個(gè)數(shù)減 1 為外循環(huán)次數(shù)
outlp: mov dx,cx ;dx ←內(nèi)循環(huán)次數(shù)
mov bx,offset array
inlp: mov al,[bx] ; 取前一個(gè)元素
cmp al,[bx+1] ; 與后一個(gè)元素比較
jna next
; 前一個(gè)不大于后一個(gè)元素,則不進(jìn)行交換
xchg al,[bx+1] ; 否則,進(jìn)行交換
mov [bx],al
next: inc bx ; 下一對(duì)元素
dec dx
jnz inlp ; 內(nèi)循環(huán)尾
loop outlp ; 外循環(huán)尾
計(jì)數(shù)控制雙重循環(huán)
; 現(xiàn)有一個(gè)以 $ 結(jié)尾的字符串,要求剔除其中的空格
.data
string db 'let us have a try !','$'
.code
.startup
mov si,offset string
outlp: cmp byte ptr [di],'$'
; 外循環(huán),先判斷后循環(huán)
jz done ; 為 $ 結(jié)束
cmp byte ptr [si],' '
; 檢測(cè)是否是空格
jnz next ; 不是空格繼續(xù)循環(huán)
例 : 剔除空格
mov di,si ; 是空格,進(jìn)入剔除空格分支
; 該分支是循環(huán)程序段
inlp: inc di
mov al,[di] ; 前移一個(gè)位置
mov [di-1],al
cmp byte ptr [di],'$'
; 內(nèi)循環(huán),先循環(huán)后判斷
jnz inlp
jmp outlp
next: inc si ; 繼續(xù)對(duì)后續(xù)字符進(jìn)行處理
jmp outlp
done: .exit 0 ; 結(jié)束