第5章 循环与分支程序设计 循环程序设计 分支程序设计
顺序结构 循环结构 程序结构: 分支结构 子程序结构 … 复合结构:多种程序结构的组合
编制汇编语言程序的步骤: (1) 分析题意,确定算法 (2) 根据算法画出程序框图 (3) 根据框图编写程序 (4) 上机调试程序
1. 循环程序设计 初始化 初始化 N 循环体 控制条件 Y N 控制条件 循环体 Y DO-WHILE 结构 DO-UNTIL 结构
初始化:设置循环的初始状态 循环体:循环的工作部分及修改部分 控制条件:计数控制 特征值控制 地址边界控制
例:把 BX 中的二进制数以十六进制的形式显示在屏幕上 1 2 3 4
…… 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
1 2 5 31 32 35 例:从键盘接收十进制数并存入 BX …… mov bx, 0 newchar: mov ah, 1 ;键盘输入 1 2 5 31 32 35 …… 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 add bx, ax jmp newchar exit: …… ( ( 0×10)+1 )×10+2 )×10+5
1 a f 31 61 66 例:从键盘接收十六进制数并存入 BX …… 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: …… ((0×16)+1) × 16+0a) × 16+0f
例:将正数 n 插入一个已整序的正数字数组 …… mov ax, n mov array_head-2, 0ffffh mov si, 0 x dw ? array_head dw 3,5,15,23,37,49,52,65,78,99 array_end dw 105 n dw 32 x -1 …… 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 array_head 5 15 23 37 49 52 65 78 99 105 array_end n 32
例: 将首地址为A的字数组从小到大排序 (气泡算法,多重循环) 32,85,16,15, 8 序号 地址 数 比 较 遍 数 1 2 3 4 1 A 32 2 A+2 85 3 A+4 16 4 A+6 15 5 A+8 8 32 16 15 8 85
mov cx, 5 ;元素个数 dec cx ;比较遍数 loop1: mov di, cx ;比较次数 mov bx, 0 loop2: mov ax, A[bx] ;相邻两数 cmp ax, A[bx+2] ; 比较 jle continue xchg ax, A[bx+2] ;交换位置 mov A[bx], ax continue: add bx, 2 loop loop2 mov cx, di loop loop1
2. 分支程序设计 CASE 结构 IF-THEN-ELSE 结构 ? ? … case 1 case 2 case n 2. 分支程序设计 ? ? … case 1 case 2 case n case 1 case 2 case n CASE 结构 IF-THEN-ELSE 结构 (1) 逻辑尺控制 (2) 条件控制 (3) 地址跳跃表(值与地址有对应关系的表)
例:有数组 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 加法
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 ;0000,0000,1101,1100 …… 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
例:折半查找算法 data segment data ends 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
折半算法1 (ax)=55 low_idx 1 4 5 high_idx 12 12 11 22 33 44 1 2 3 4 5 6 7 8 9 10 11 12 12 11 22 33 44 55 66 77 88 99 111 222 333 (si)=0ah Cf=0 (ax)=90 low_idx 1 7 8 9 high_idx 12 (si)=10h Cf=1
算法1 …… 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)=最后一个元素,找到退出 jmp exit ; (ax)>最后一个元素,未找到退出 算法1
search: mov low_idx, 1 mov bx, [di] ;个数 compare: mov high_idx, bx 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 compare: cmp ax, [bx+si] je exit ja higher dec cx mov high_idx, cx jmp mid higher: inc cx mov low_idx, cx no_match: stc exit: ……
折半算法2 (ax)=55 di 12 6 10 si 4 1 2 3 4 5 6 7 8 9 10 11 12 12 11 22 33 44 55 66 77 88 99 111 222 333 (si)=0ah (di)=0ah Cf=0 (ax)=90 di 12 18 14 16 si 6 4 2 (si)=2 (di)=10h Cf=1
算法2 search: idx_ok: shr si, 1 test si, 1 jz sub_idx inc si sub di, si jmp short compare higher: cmp si, 2 je no_match 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
例:根据 AL 寄存器中哪一位为 1(从低位到高位), 把程序转移到 8 个不同的程序分支 branch_table dw routine1 dw routine2 dw routine3 dw routine4 dw routine5 dw routine6 dw routine7 dw routine8
(寄存器间接寻址) …… cmp al, 0 ;AL为逻辑尺 je continue lea bx, branch_table L: shr al, 1 ;逻辑右移 jnc add1 jmp word ptr[bx] ;段内间接转移 add1: add bx, type branch_table ;add bx,2 jmp L continue: routine1: routine2:
(寄存器相对寻址) …… cmp al, 0 je continue mov si, 0 L: shr al, 1 ;逻辑右移 jnc add1 jmp branch_table[si] ;段内间接转移 add1: add si, type branch_table jmp L continue: routine1: routine2:
…… (基址变址寻址) cmp al, 0 je continue lea bx, branch_table mov si, 7 * type branch_table mov cx, 8 L: shl al, 1 ;逻辑左移 jnc sub1 jmp word ptr [bx][si] ;段内间接转移 sub1: sub si, type branch_table ;(si)-2 loop L continue: routine1: routine2: (基址变址寻址)
第5章作业 Page 193 5.5 5.7 5.12 5.18