第5章 循环与分支程序设计 学习目标: 了解并掌握循环程序的构造方法,尤其是对循环控制条件的设置以及可能出现的边界情况的考虑。掌握起泡排序算法这种多重循环程序设计中的常用方法。交换标志位的设置在此算法中更能提高效率。学会在数组排序算法中采用折半查找法来提高查找效率。学会使用跳跃表法实现CASE结构。
§5.1 循环程序设计 一、循环程序的结构形式 二、循环程序设计 三、多重循环程序设计
一、循环程序的结构形式 结束 初始化 循环体 修改部分 控制条件 Y N 先判断,后循环
一、循环程序的结构形式 结束 初始化 循环体 修改部分 控制条件 Y N 先循环,后判断
prognam segment assume cs:prognam start: mov ch,4 rotate: mov cl,4 rol bx,cl mov al,bl and al,0fh add al,30h cmp al,3ah jl printit add al,7h printit: mov dl,al mov ah,2 int 21h dec ch jnz rotate mov ah,4ch int 21h prognam ends end start
例5.2 在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中 开始 1的个数计数器←0 循环次数计数器CX←16 Y左移一次 CF=1 1的个数计数器+1 CX ←CX-1=0 COUNT ← 1的个数计数器 结束 N Y 例5.2 在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中 循环次数固定,完全由循环计数器控制
例5.2 DATA SEGMENT REPEAT: Y DW 1234H ADDR DW Y SHL AX,1 COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL MOV AH,4CH INT 21H CODE ENDS END START
例5.2 Y 开始 1的个数计数器←0 循环次数计数器CX←16 Y=0 Y左移一次 N CF=1 1的个数计数器+1 CX ←CX-1=0 COUNT ← 1的个数计数器 结束 N Y Y=0 例5.2
例5.2 DATA SEGMENT Y DW 1234H ADDR DW Y COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL MOV AH,4CH INT 21H CODE ENDS END START CMP AX,0 JZ EXIT0 JMP REPEAT
循环程序设计 例 在附加段中,有一个首地址为LIST和未经排序的字数组。在数组的第一个字中,存放着该数组的长度,数组的首地址已存放在DI寄存器中,AX寄存器中存放着一个数。要求编制一程序:在数组中查找该数,如果找到此数,则把它从数组中删除。
del_ul proc near cld push di mov cx,es:[di] add di,2 repne scasw je delete pop di jmp short exit delete: jcxz dec_cnt next_el: mov bx,ex:[di] mov es:[di-2],bx add di,2 loop next_el dec_cnt: pop di dec word ptr es:[di] exit: ret del_up endp
例5.4 将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 23, 37, 49, 52 32 END HEAD 23, 37, 49, 52 32, -1, -1, 解法一: 从数组的尾部开始比较 N较大,则在比较对象后插入,结束循环 N较小,则把比较对象及其后元素后移一个字 循环结束的控制: 执行插入操作后结束循环 若N比所有元素都小,扫描整个数组后仍无法结束循环,将-1加在数组前可解决该问题
例5.4 N 开始 (ARRAY_HEAD-2)←-1 初始化变址寄存器SI Y K<=N 将N放在K的位置 K后移一个字单元 结束 修改地址 K后移一个字单元 结束 Y N
assume cs:program,ds:datarea Start: mov ax,datarea mov ds,ax 例5.4 Datarea segment x dw ? Array_head dw 3,5,15,23,37,49 Array_end dw 105 n dw 32 Datarea ends Program segment assume cs:program,ds:datarea Start: mov ax,datarea mov ds,ax mov ax,n mov array_head-2,-1 mov si,0 Comp:cmp array_end[si],ax jle insert mov bx,array_end[si] mov array_end[si+2],bx sub si,2 jmp comp Insert: mov array_end[si+2],ax mov ah,4ch int 21h Program ends end start mov bx,array_end[si] cmp bx,ax jle insert
例5.4 将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 解法二: 从数组的头部开始比较 N较小,则在比较对象前插入,结束循环 N较大,则把比较对象及其前元素前移一个字 可扫描整个数组,循环次数为数组元素个数 执行插入操作后结束循环 循环结束的控制: 若N比所有元素都小,形成新的头;若N比所有元素都大,则被置于尾部
例5.4
例5 设有数组X (X1,…,X10) 和Y (Y1,…,Y10) ,编程计算数组Z (Z1,…,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
mov ax,x[bx] shr dx,1 jc subtract add ax,y[bx] jmp short result datarea segment 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 datarea ends prognam segment assume cs:prognam,ds:datarea start: mov ax,datarea mov ds,ax 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 mov ah,4ch int 21h prognam ends end start
例5.5 试编制一程序:从键盘输入一行字符,要求第一个键入的字符必须是空格符,如不是,则退出程序;如是,则开始接收键入的字符并顺序存放在首地址为BUFFER的缓冲区中(空格符不存入),直到接收到第二个空格符时退出程序。
datarea segment buffer db 80 dup(?) flag db ? next: mov ah,01 int 21h test flag,01h jnz follow cmp al,20h jnz exit mov flag,1 jmp next follow: cmp al,20h jz exit mov [bx],al inc bx jmp next exit: mov ah,4ch int 21h prognam ends end start datarea segment buffer db 80 dup(?) flag db ? datarea ends prognam segment assume cs:prognam,ds:datarea start: mov ax,datarea mov ds,ax lea bx,buffer mov flag,0
三、多重循环程序设计 例5.7 有一个首地址为A的N字数组,请编制程序使该数组中的数按照从大到小的次序整序 冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不大于后一个元素;将所有元素比较完之后,最大的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次大的元素排在后面;如此重复,直至完成就实现元素从小到大的排序 这需要一个双重循环程序结构
冒泡法的排序 序号 数 比 较 遍 数 1 2 3 4 1 32 2 85 3 16 4 15 5 8 32 16 15 8 85
例5.7-1
例5.7-2
§5.2 分支程序设计 一、分支程序的结构形式 二、分支程序的设计 三、跳跃表
一、分支程序的结构形式
二、分支程序的设计 例 在附加段中,有一个按从小到大顺序排列的无符号数数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组长度。在AX中有一个无符号数,要求在数组中查找(AX),如找到,则使CF = 0,并在SI中给出该元素在数组中的偏移地址;如未找到,则使CF = 1。
三、跳跃表