1
? 循环程序设计
? 分支程序设计
第五章 循环与分支程序设计
2
编制汇编语言程序的步骤,
(1) 分析题意,确定算法
(2) 根据算法画出程序框图
(3) 根据框图编写程序
(4) 上机调试程序
3
程序结构,
分支结构 子程序结构
复合结构:多种程序结构的组合
…
顺序结构 循环结构
4
1,循环程序设计
DO-WHILE 结构 DO-UNTIL 结构
控制条件
初始化
循环体
Y
N
控制条件
初始化
循环体
Y
N
5
初始化, 设置循环的初始状态
循环体, 循环的工作部分及修改部分
控制条件, 计数控制
特征值控制
地址边界控制
6
BX
1
2
3
4
例:把 BX中的二进制数以十六进制的形式显示在屏幕上
7
……
mov ch,4
rotate,mov cl,4
rol bx,cl
mov al,bl
and al,0fh
add al,30h ; ’0’~’9’ ASCII 30H~39H
cmp al,3ah
jl printit
add al,7h ; ’A’~’F’ ASCII 41H~46H
printit,mov dl,al
mov ah,2
int 21h
dec ch
jnz rotate
……
8
……
mov bx,0
newchar,mov ah,1
int 21h
sub al,30h
jl exit ; <0 退出
cmp al,9
jg exit ; >9 退出
cbw
xchg ax,bx
mov cx,10
mul cx
xchg ax,bx
add bx,ax
jmp newchar
exit,……
例:从键盘接收十进制数并存入 BX
9
……
mov bx,0
newchar,mov ah,1
int 21h
sub al,30h
jl exit ; <0 退出
cmp al,10
jl add_to
sub al,27h ; ‘a’~‘f’
cmp al,0ah
jl exit ; <‘a’ 退出
cmp al,10h
jge exit ; >’f’ 退出
add_to,mov cl,4
shl bx,cl
mov ah,0
add bx,ax
jmp newchar
exit,……
例:从键盘接收十六进制数并存入 BX
10
x dw?
array_head dw 3,5,15,23,37,49,52,65,78,99
array_end dw 105
n dw 32
例:将正数 n 插入一个已整序的正数字数组
……
mov ax,n
mov array_head-2,0ffffh
mov si,0
compare,
cmp array_end[si],ax
jle insert
mov bx,array_end[si]
mov array_end[si+2],bx
sub si,2
jmp short compare
insert,
mov array_end[si+2],ax
……
3
5
15
23
37
49
52
65
78
99
105
32
-1
array_head?
array_end?
n ?
x ?
11
例:将首地址为 a 的字数组从大到小排序
( 起泡排序算法,多重循环 )
100
30
78
99
15
-1
66
45
189
256
100
78
99
30
15
66
45
189
256
-1
100
99
78
30
66
45
189
256
15
-1
100
99
78
66
45
189
256
30
15
-1
100
99
78
66
189
256
45
30
15
-1
100
99
78
189
256
66
45
30
15
-1
100
99
189
256
78
66
45
30
15
-1
100
189
256
99
78
66
45
30
15
-1
189
256
100
99
78
66
45
30
15
-1
256
189
100
99
78
66
45
30
15
-1
? ? ? ? ? ? ? ? ?
12
a dw 100,30,78,99,15,-1,66,45,189,256
……
mov cx,10
dec cx
loop1,mov di,cx
mov bx,0
loop2,
mov ax,a[bx]
cmp ax,a[bx+2]
jge continue
xchg ax,a[bx+2]
mov a[bx],ax
continue,
add bx,2
loop loop2
mov cx,di
loop loop1
……
13
2,分支程序设计
…
case 1 case 2 case n
case 1 case 2 case n
CASE 结构 IF-THEN-ELSE 结构
(1) 逻辑尺控制
(2) 条件控制
(3) 地址跳跃表 (值与地址有对应关系的表)
14
例:有数组 x(x1,x2,……,x10) 和 y(y1,y2,……,y10),
编程计算 z(z1,z2,……,z10)
z1 = x1 + y1
z2 = x2 + y2
z3 = x3 - y3
z4 = x4 - y4
z5 = x5 - y5
z6 = x6 + y6
z7 = x7 - y7
z8 = x8 - y8
z9 = x9 + y9
z10= x10 + y10
逻辑尺,0 0 1 1 0 1 1 1 0 0
1 减法
0 加法
15
x dw x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
y dw y1,y2,y3,y4,y5,y6,y7,y8,y9,y10
z dw z1,z2,z3,z4,z5,z6,z7,z8,z9,z10
logic_rule dw 00dch
……
mov bx,0
mov cx,10
mov dx,logic_rule
next,mov ax,x[bx]
shr dx,1
jc subtract
add ax,y[bx]
jmp short result ; 向前引用
subtract,
sub ax,y[bx]
result,mov z[bx],ax
add bx,2
loop next
……
16
data segment
array dw 12,11,22,33,44,55,66,
77,88,99,111,222,333
number dw 55
low_idx dw?
high_idx dw?
data ends
例:折半查找算法
17
……
lea di,array
mov ax,number
cmp ax,[di+2] ; (ax)与第一个元素比较
ja chk_last
lea si,[di+2]
je exit ; (ax)=第一个元素,找到退出
stc
jmp exit ; (ax)<第一个元素,未找到退出
chk_last,
mov si,[di]
shl si,1
add si,di
cmp ax,[si] ; (ax)与最后一个元素比较
jb search
je exit ; (ax)=最后一个元素,找到退出
stc
jmp exit ; (ax)>最后一个元素,未找到退出
算法 1
18
compare,
cmp ax,[bx+si]
je exit
ja higher
dec cx
mov high_idx,cx
jmp mid
higher,
inc cx
mov low_idx,cx
jmp mid
no_match,
stc
exit,
……
search,
mov low_idx,1
mov bx,[di]
mov high_idx,bx
mov bx,di
mid,
mov cx,low_idx
mov dx,high_idx
cmp cx,dx
ja no_match
add cx,dx
shr cx,1
mov si,cx
shl si,1
19
12
11
22
33
44
55
66
77
88
99
111
222
333
0
1
2
3
4
5
6
7
8
9
10
11
12
(ax)=55
low_idx
1
1
4
5
high_idx
12
5
5
5
(si)=0ah
Cf=0
(ax)=90
low_idx
1
7
7
8
9
high_idx
12
12
8
8
8
(si)=10h
Cf=1
?
?
?
?
20
算法 2 idx_ok,
shr si,1
test si,1
jz sub_idx
inc si
sub_idx,
sub di,si
jmp short compare
higher,
cmp si,2
je no_match
shr si,1
jmp short even_idx
all_done,
mov si,di
exit,
……
search,
mov si,[di]
even_idx,
test si,1
jz add_idx
inc si
add_idx,
add di,si
compare,
cmp ax,[di]
je all_done
ja higher
cmp si,2
jne idx_ok
no_match,
stc
jmp exit
21
12
11
22
33
44
55
66
77
88
99
111
222
333
0
1
2
3
4
5
6
7
8
9
10
11
12
(ax)=55
di
12
6
10
si
12
6
4
(si)=0ah
(di)=0ah
Cf=0
(ax)=90
di
12
18
14
16
si
12
6
4
2
(si)=2
(di)=10h
Cf=1
?
?
?
22
例:根据 AL 寄存器中哪一位为 1( 从低位到高位 ),
把程序转移到 8 个不同的程序分支
branch_table dw routine1
dw routine2
dw routine3
dw routine4
dw routine5
dw routine6
dw routine7
dw routine8
23
……
cmp al,0
je continue
lea bx,branch_table
L,shr al,1 ;逻辑右移
jnb add1 ;jnb=jnc
jmp word ptr[bx] ;段内间接转移
add1,add bx,type branch_table
jmp L
continue,
……
routine1,
……
routine2,
……
( 寄存器间接寻址 )
24
( 寄存器相对寻址 ) …… cmp al,0
je continue
mov si,0
L,shr al,1 ;逻辑右移
jnb add1 ;jnb=jnc
jmp branch_table[si] ;段内间接转移
add1,
add si,type branch_table
jmp L
continue,
……
routine1,
……
routine2,
……
25
( 基址变址寻址 ) …… cmp al,0
je continue
lea bx,branch_table
mov si,7 * type branch_table
mov cx,8
L,shl al,1 ;逻辑左移
jnb sub1 ;jnb=jnc
jmp word ptr [bx][si] ;段内间接转移
sub1,sub si,type branch_table
loop L
continue,
……
routine1,
……
routine2,
……
26
作业,
p156 5.5 5.7 5.12 5.17 5.18 5.19
27
实验 1 键盘接收 0 ~ 9 之间的数,屏幕输出如下形式(以输入 6 为例),
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
5 5 5 5 5
4 4 4 4
3 3 3
2 2
1
实验 2 带符号数的十六进制和十进制之间的转换,键盘接收,屏幕显示。
要求,1,有简单的菜单提示
2,16 ?10 ‘a’~’f’ 和 ’ A’~’F’ 都可接收
3,10 ?16 对正数而言,123 和 +123 都可接收
4,不考虑溢出(字长 16 bit)
? 循环程序设计
? 分支程序设计
第五章 循环与分支程序设计
2
编制汇编语言程序的步骤,
(1) 分析题意,确定算法
(2) 根据算法画出程序框图
(3) 根据框图编写程序
(4) 上机调试程序
3
程序结构,
分支结构 子程序结构
复合结构:多种程序结构的组合
…
顺序结构 循环结构
4
1,循环程序设计
DO-WHILE 结构 DO-UNTIL 结构
控制条件
初始化
循环体
Y
N
控制条件
初始化
循环体
Y
N
5
初始化, 设置循环的初始状态
循环体, 循环的工作部分及修改部分
控制条件, 计数控制
特征值控制
地址边界控制
6
BX
1
2
3
4
例:把 BX中的二进制数以十六进制的形式显示在屏幕上
7
……
mov ch,4
rotate,mov cl,4
rol bx,cl
mov al,bl
and al,0fh
add al,30h ; ’0’~’9’ ASCII 30H~39H
cmp al,3ah
jl printit
add al,7h ; ’A’~’F’ ASCII 41H~46H
printit,mov dl,al
mov ah,2
int 21h
dec ch
jnz rotate
……
8
……
mov bx,0
newchar,mov ah,1
int 21h
sub al,30h
jl exit ; <0 退出
cmp al,9
jg exit ; >9 退出
cbw
xchg ax,bx
mov cx,10
mul cx
xchg ax,bx
add bx,ax
jmp newchar
exit,……
例:从键盘接收十进制数并存入 BX
9
……
mov bx,0
newchar,mov ah,1
int 21h
sub al,30h
jl exit ; <0 退出
cmp al,10
jl add_to
sub al,27h ; ‘a’~‘f’
cmp al,0ah
jl exit ; <‘a’ 退出
cmp al,10h
jge exit ; >’f’ 退出
add_to,mov cl,4
shl bx,cl
mov ah,0
add bx,ax
jmp newchar
exit,……
例:从键盘接收十六进制数并存入 BX
10
x dw?
array_head dw 3,5,15,23,37,49,52,65,78,99
array_end dw 105
n dw 32
例:将正数 n 插入一个已整序的正数字数组
……
mov ax,n
mov array_head-2,0ffffh
mov si,0
compare,
cmp array_end[si],ax
jle insert
mov bx,array_end[si]
mov array_end[si+2],bx
sub si,2
jmp short compare
insert,
mov array_end[si+2],ax
……
3
5
15
23
37
49
52
65
78
99
105
32
-1
array_head?
array_end?
n ?
x ?
11
例:将首地址为 a 的字数组从大到小排序
( 起泡排序算法,多重循环 )
100
30
78
99
15
-1
66
45
189
256
100
78
99
30
15
66
45
189
256
-1
100
99
78
30
66
45
189
256
15
-1
100
99
78
66
45
189
256
30
15
-1
100
99
78
66
189
256
45
30
15
-1
100
99
78
189
256
66
45
30
15
-1
100
99
189
256
78
66
45
30
15
-1
100
189
256
99
78
66
45
30
15
-1
189
256
100
99
78
66
45
30
15
-1
256
189
100
99
78
66
45
30
15
-1
? ? ? ? ? ? ? ? ?
12
a dw 100,30,78,99,15,-1,66,45,189,256
……
mov cx,10
dec cx
loop1,mov di,cx
mov bx,0
loop2,
mov ax,a[bx]
cmp ax,a[bx+2]
jge continue
xchg ax,a[bx+2]
mov a[bx],ax
continue,
add bx,2
loop loop2
mov cx,di
loop loop1
……
13
2,分支程序设计
…
case 1 case 2 case n
case 1 case 2 case n
CASE 结构 IF-THEN-ELSE 结构
(1) 逻辑尺控制
(2) 条件控制
(3) 地址跳跃表 (值与地址有对应关系的表)
14
例:有数组 x(x1,x2,……,x10) 和 y(y1,y2,……,y10),
编程计算 z(z1,z2,……,z10)
z1 = x1 + y1
z2 = x2 + y2
z3 = x3 - y3
z4 = x4 - y4
z5 = x5 - y5
z6 = x6 + y6
z7 = x7 - y7
z8 = x8 - y8
z9 = x9 + y9
z10= x10 + y10
逻辑尺,0 0 1 1 0 1 1 1 0 0
1 减法
0 加法
15
x dw x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
y dw y1,y2,y3,y4,y5,y6,y7,y8,y9,y10
z dw z1,z2,z3,z4,z5,z6,z7,z8,z9,z10
logic_rule dw 00dch
……
mov bx,0
mov cx,10
mov dx,logic_rule
next,mov ax,x[bx]
shr dx,1
jc subtract
add ax,y[bx]
jmp short result ; 向前引用
subtract,
sub ax,y[bx]
result,mov z[bx],ax
add bx,2
loop next
……
16
data segment
array dw 12,11,22,33,44,55,66,
77,88,99,111,222,333
number dw 55
low_idx dw?
high_idx dw?
data ends
例:折半查找算法
17
……
lea di,array
mov ax,number
cmp ax,[di+2] ; (ax)与第一个元素比较
ja chk_last
lea si,[di+2]
je exit ; (ax)=第一个元素,找到退出
stc
jmp exit ; (ax)<第一个元素,未找到退出
chk_last,
mov si,[di]
shl si,1
add si,di
cmp ax,[si] ; (ax)与最后一个元素比较
jb search
je exit ; (ax)=最后一个元素,找到退出
stc
jmp exit ; (ax)>最后一个元素,未找到退出
算法 1
18
compare,
cmp ax,[bx+si]
je exit
ja higher
dec cx
mov high_idx,cx
jmp mid
higher,
inc cx
mov low_idx,cx
jmp mid
no_match,
stc
exit,
……
search,
mov low_idx,1
mov bx,[di]
mov high_idx,bx
mov bx,di
mid,
mov cx,low_idx
mov dx,high_idx
cmp cx,dx
ja no_match
add cx,dx
shr cx,1
mov si,cx
shl si,1
19
12
11
22
33
44
55
66
77
88
99
111
222
333
0
1
2
3
4
5
6
7
8
9
10
11
12
(ax)=55
low_idx
1
1
4
5
high_idx
12
5
5
5
(si)=0ah
Cf=0
(ax)=90
low_idx
1
7
7
8
9
high_idx
12
12
8
8
8
(si)=10h
Cf=1
?
?
?
?
20
算法 2 idx_ok,
shr si,1
test si,1
jz sub_idx
inc si
sub_idx,
sub di,si
jmp short compare
higher,
cmp si,2
je no_match
shr si,1
jmp short even_idx
all_done,
mov si,di
exit,
……
search,
mov si,[di]
even_idx,
test si,1
jz add_idx
inc si
add_idx,
add di,si
compare,
cmp ax,[di]
je all_done
ja higher
cmp si,2
jne idx_ok
no_match,
stc
jmp exit
21
12
11
22
33
44
55
66
77
88
99
111
222
333
0
1
2
3
4
5
6
7
8
9
10
11
12
(ax)=55
di
12
6
10
si
12
6
4
(si)=0ah
(di)=0ah
Cf=0
(ax)=90
di
12
18
14
16
si
12
6
4
2
(si)=2
(di)=10h
Cf=1
?
?
?
22
例:根据 AL 寄存器中哪一位为 1( 从低位到高位 ),
把程序转移到 8 个不同的程序分支
branch_table dw routine1
dw routine2
dw routine3
dw routine4
dw routine5
dw routine6
dw routine7
dw routine8
23
……
cmp al,0
je continue
lea bx,branch_table
L,shr al,1 ;逻辑右移
jnb add1 ;jnb=jnc
jmp word ptr[bx] ;段内间接转移
add1,add bx,type branch_table
jmp L
continue,
……
routine1,
……
routine2,
……
( 寄存器间接寻址 )
24
( 寄存器相对寻址 ) …… cmp al,0
je continue
mov si,0
L,shr al,1 ;逻辑右移
jnb add1 ;jnb=jnc
jmp branch_table[si] ;段内间接转移
add1,
add si,type branch_table
jmp L
continue,
……
routine1,
……
routine2,
……
25
( 基址变址寻址 ) …… cmp al,0
je continue
lea bx,branch_table
mov si,7 * type branch_table
mov cx,8
L,shl al,1 ;逻辑左移
jnb sub1 ;jnb=jnc
jmp word ptr [bx][si] ;段内间接转移
sub1,sub si,type branch_table
loop L
continue,
……
routine1,
……
routine2,
……
26
作业,
p156 5.5 5.7 5.12 5.17 5.18 5.19
27
实验 1 键盘接收 0 ~ 9 之间的数,屏幕输出如下形式(以输入 6 为例),
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
5 5 5 5 5
4 4 4 4
3 3 3
2 2
1
实验 2 带符号数的十六进制和十进制之间的转换,键盘接收,屏幕显示。
要求,1,有简单的菜单提示
2,16 ?10 ‘a’~’f’ 和 ’ A’~’F’ 都可接收
3,10 ?16 对正数而言,123 和 +123 都可接收
4,不考虑溢出(字长 16 bit)