版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第5章 循环与分支程序设计【课前思考】1. 编制一个汇编语言程序分哪几步?2. 循环程序有哪两种基本结构?由几部分组成?3. 设计算法时对可能出现的边界情况如何考虑?4. 如何设置逻辑尺?5. 什么是起泡排序算法?6. 如何理解数组排序算法中采用的折半查找法?7. 如何使用跳跃表法实现CASE结构?【学习目标】了解并掌握循环程序的构造方法,尤其是对循环控制条件的设置以及可能出现的边界情况的考虑。掌握起泡排序算法这种多重循环程序设计中的常用方法。交换标志位的设置在此算法中更能提高效率。学会在数组排序算法中采用折半查找法来提高查找效率。学会使用跳跃表法实现CASE结构。【学习指南】掌握编程的四个步
2、骤至关重要。通过多看举例,学会正确分析理解题意、选择合适的数据结构及算法、坚持先画框图、选取有效指令编程、最后应当掌握运用调试手段进行调试。学习多重循环程序设计前应熟练掌握单层循环程序设计的各种实现方法及实现细节,如对可能出现的边界情况的处理等。学习起泡排序算法、折半查找法、跳跃表法之前,应首先理解传统实现方法。【难重点】循环控制条件的选择。考虑循环算法时注意可能出现的边界情况。静态地预置逻辑尺。动态地修改标志位。多重循环程序设计时应分别考虑各重循环的控制条件及其程序实现,相互之间不能混淆。另外,应该注意在每次通过外层循环再次进入内层循环时,初始条件必须重新设置。起泡排序算法是多重循环程序设计
3、中的一种常用方法。数组排序算法中可以采用折半查找法来提高查找效率。CASE结构可以使用跳跃表法实现。【知识点】编制一个汇编语言程序的一般步骤5.1 循环程序设计5.1.1 循环程序的基本结构5.1.2 循环程序设计方法举例循环控制条件边界情况的处理逻辑尺5.1.3 多重循环程序设计举例起泡排序算法交换标志位5.2 分支程序设计5.2.1 分支程序的基本结构5.2.2 分支程序设计方法举例折半查找法5.2.3 跳跃表法一般说来,编制一个汇编语言程序的步骤如下:1) 分析题意,确定算法。2) 根据算法,画出程序框图。3) 根据框图编写程序。4)上机调试程序。程序有顺序、循环、分支和子程序四种结构形
4、式。顺序程序结构是指完全按顺序逐条执行的指令序列,这在程序段中是大量存在的,但作为完整的程序则很少见,我们不对它们作专门讨论。5.1 循环程序设计5.1.1 循环程序的结构形式及组成循环程序可以有两种结构形式,如图所示。一种是DO_WHILE结构形式;另一种是DO_UNTIL结构形式。初始化:设置循环的初始状态;循环体:循环的工作部分及修改部分;控制条件:计数控制、特征值控制、地址边界控制。例5.1 试编制一个程序,把BX寄存器中的二进制数以十六进制的形式显示在屏幕上。解析:根据题目要求应将BX中的内容从左到右每4位一组显示出来,共显示4个十六进制数位。如果显示的数位是09,则把4位二进制数加
5、上30H,转换成相应的ASCII码30H39H;如果是AF,则应加上37H(30H+7),转换成ASCII码41H46H。显示字符可以使用DOS功能调用来实现。右图是程序框图(P162页)。以binihex.asm为文件名,建立源程序如下:; binihex.asmprognam segment ; 定义代码段main proc far assume cs:prognam start: ; 程序从此处开始执行 ; 为正常返回DOS而设置堆栈 push ds sub ax,ax push ax ; 下面是程序的主要部分mov ch,4 ; 4组二进制数rotate: mov cl,4; 每组4个
6、二进制位rol bx,cl ; 把bx循环左移4位mov al,bl ; 暂存bl到al中and al,0fh ; 仅保留al的低4位add al,30h; 转换成ASCII码cmp al,3ah; 要显示的数大于9 ?jl printit ; 如果数在09之间则显示add al,7h ; 数在AF之间则调整printit:mov dl,al ; 把要显示字符的ASCII码送dlmov ah,2 ; 功能号2送ahint 21h ; DOS功能调用dec ch ; (ch)-1jnz rotate ; 4组都处理完?否,循环处理下一组ret ; 返回DOSmain endp ; 主程序main
7、结束prognam ends ; 代码段结束end start ; 结束汇编例5.2从键盘接收十进制数并存入 BXprognamsegmentmain proc farassumecs:prognam start:pushdssubax,axpushaxmov bx, 0newchar:mov ah, 1;键盘输入int 21hsub al, 30hjl exit;9退出cbw例5.3从键盘接收十六进制数并存入 BXcodesegment assume cs:code, ds:data start:movax,4c00hint21h ; 返回DOScodeendsendstart例5.4 将正
8、数N插入一个已整序的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_HEAD和ARRAY_END,其中所有数均为正数且已按递增的次序排列。; 定义数据段datareasegmentx dw?array_head dw23,37,49,52,65,78,99array_enddw105ndw32 datareaends; 定义代码段prognamsegmentmainprocfar ; 主程序部分assume cs:prognam,ds:datareastart:; 程序从此处开始执行pushdssubax,ax pushaxmovax,datareamovds,ax; 程序的主要部分
9、movax,nmovarray_head-2,0ffffh ; -1送array_head-2单元movsi,0compare:cmparray_endsi,axjleinsertmovbx,array_endsimovarray_endsi+2,bxsubsi,2jmpshort compareinsert:movarray_endsi+2,axretmainendp ; 主程序main结束prognam endsendstart例5.5 设有数组X (X1,X10) 和Y (Y1,Y10) ,编程计算数组Z (Z1,Z10) ,其中:Z1 = X1 + Y1 Z2 = X2 + Y2 Z3
10、 = X3 - Y3Z4 = X4 - Y4Z5 = X5 - Y5 Z6 = X6 + Y6 Z7 = X7 - Y7 Z8 = X8 - Y8 Z9 = X9 + Y9 Z10 = X10 + Y10; 定义数据段datareasegment xdwx1,x2,x3,x4,x5,x6.x7,x8,x9,x10y dwy1,y2,y3,y4,y5,y6,y7,y8,y9,y10z dwz1,z2,z3,z4,z5,z6,z7,z8,z9,z10logic_ruledw00dchdatareaends; 定义代码段prognamsegmentmainprocfarassumecs:progna
11、m,ds:datareastart: pushds subax,ax pushax movax,datarea movds,ax movbx,0movcx,10movdx,logic_rulenext: movax,xbxshrdx,1jcsubtractaddax,ybxjmpshort resultsubtract:subax,ybxresult:movzbx,axaddbx,2loopnextretmainendp prognamends endstart这种设置逻辑尺的方法是很常用的。例如,在矩阵运算中,为了跳过操作数为0的计算,经常采用这种方法。又如,把一组数据存入存储器时,如果其中
12、数值为0的元素很多,也可用这种方法设立一个每位表示一个下标的逻辑尺(这样的逻辑尺可能占有几个字,由数组的长度确定。),0元素就可不占有存储单元了。在例5.5中,每个标志只占一位,如果要表示的特征数更多,则每个标志可占有几位,而在处理方法上是完全相同的。设立标志位的方法除了如逻辑尺那样可静态地预置外,还可以在程序中动态地修改标志位的值,以达到控制的目的,下例将说明这种方法。例5.5 试编制一程序:从键盘输入一行字符,要求第一个键入的字符必须是空格符,如不是,则退出程序;如是,则开始接收键入的字符并顺序存放在首地址为BUFFER的缓冲区中(空格符不存入),直到接收到第二个空格符时退出程序。 这一程
13、序要求接收的字符从空格符开始又以空格符结束,因此程序中必须区分所接收的字符是否是第一个字符。为此,设立作为标志的存储单元FLAG。一开始将其置为0,接收第一个字符后可将其置1。整个程序的框图如图所示。; 定义数据段datareasegmentbufferdb80 dup(?)flagdb?datareaends; 定义代码段prognamsegment mainprocfarassumecs:prognam,ds:datareastart:pushdssubax,axpushaxmovax,datareamovds,axleabx,buffermovflag,0next: mov ah,01i
14、nt21htestflag,01hjnz/jnefollowcmpal,20hjnz/jneexitmovflag,1jmpnextfollow: cmpal,20hjz/jeexitmovbx,alincbxjmpnextexit: ret mainendp prognam ends end start 例5.6 有一个首地址为A的N字数组,请编制程序使该数组中的数按照从小到大的次序整序。解析:这里采用起泡排序算法实现数组整序。从第一个数开始依次对相邻两个数Ki和Ki+1进行比较,若KiKi+1,Ki的位置不动,Ki+1继续和Ki+2比较;若KiKi+1,则两者交换位置,Ki+1(交换前的K
15、i)继续和Ki+2比较。(P172页)(气泡算法,多重循环) 32,85,16,15, 8; 定义数据段dsegsegmentnequ5 ; 数组中数的个数adwn dup(?)dseg ends; 定义代码段csegsegmentmainprocfarassumecs:cseg, ds:dsegstart:movax,dsegmovds,axmovcx,ndeccx; 设置count1loop1:movdi,cx; 保存count1movsi, 0; 初始化siloop2:movax,asicmpax,asi+2; Ki与Ki+1比较jlecontinue; 如果KiKi+1,不交换xchg
16、ax,asi+2movasi,ax; 如果KiKi+1,交换continue:addsi,2; 修改地址looploop2; 内循环movcx,di; 恢复count1looploop1; 外循环movax,4c00hint21hmainendpcsegendsendstart5.2 分支程序设计分支程序有两种基本结构,如图所示。它们分别相当于高级语言中的IF_THEN_ELSE语句和CASE语句,适用于要求根据不同条件作不同处理的情况。IF_THEN_ELSE语句可以引出两个分支,CASE语句则可以引出多个分支,不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行
17、多个分支中的一个分支。csegsegmentmainprocnearassumecs:cseg, ds:datastart:movax,dsegmovds,axexit:movax,4c00hint21hmainendpcsegendsendstart例: 试根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支中去。branch_addresses segment ; 定义数据段branch_table dw routine_1 dw routine_2 dw routine_3 dw routine_4 dw routine_5 dw routine_6 dw routi
18、ne_7 dw routine_8branch_addresses endsprocedure_select segment ; 定义代码段main proc far ; 定义主程序mainassume cs:procedure_select,ds:branch_addressesstart: push ds sub bx,bx push bx mov bx,branch_addresses mov ds,bx; 程序的主要部分(寄存器相对寻址) cmp al,0 ; (al)=0? je continue ; (al)为0则转到continue_main_line mov si,0l: sh
19、r al,1 ; 把al逻辑右移1位 jnc not_yet ; CF=0转到not_yet jmp branch_tablesi ; CF=1转到相应程序分支 not_yet: add si,type branch_table ; 修改地址add si,2 jmp l ; 无条件跳到l continue: ; 其它程序段 routine_1: ; 程序段1routine_2: ; 程序段2 ret main endp ; 主程序main结束procedure_select ends end start用寄存器间接寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分):cmp al,0
20、 je continue lea bx,branch_table ; branch_table的偏移地址送bx l: shr al,1 jnc not_yet ; CF=0转到not_yetjmp word ptrbx ; CF=1转到相应程序分支 not_yet: add bx,type branch_table ; 修改地址jmp l ; 无条件跳到l continue: 用基址变址寻址方式实现跳跃表法的程序如下(仅给出修改后的程序的主要部分),与前两种寻址方式的主要区别是这里使用了逻辑左移指令,即从al的高位向低位判断,而前两段程序是从al的低位向高位判断。cmp al,0 je continuelea bx,branch_table mov si,7*type branch_table ; 14送simov cx,8 ; 循环次数8送cx l: shl al,1 ; 把al逻辑左移1位jnb not_yet ; CF=0转到not_yetjmp word ptrbxsi ; CF=1转到相应程序分支 not_yet: sub si,type branch_table ; 修改地址loopl ; 循环continue: 以上多个例子都是既有分支结构又有循环结构,实际上,多数程序都是各种程序结构的组合。而且,循环结构可以看作分支结构的一种特例,它只是多次走一个分支,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年广东南华工商职业学院单招职业技能考试题库带答案详解(轻巧夺冠)
- 2026年广东省韶关市单招职业适应性测试题库及答案详解(必刷)
- 2026年广西农业工程职业技术学院单招职业倾向性测试题库附参考答案详解(预热题)
- 2026年山西省朔州市单招职业适应性测试题库含答案详解(b卷)
- 2026年山西铁道职业技术学院单招职业倾向性考试题库含答案详解(夺分金卷)
- 2026年广东科贸职业学院单招职业倾向性测试题库含答案详解(能力提升)
- 2026年广州番禺职业技术学院单招职业适应性考试题库附答案详解(培优)
- 2026年广州番禺职业技术学院单招职业技能考试题库附参考答案详解(典型题)
- 2026年广州科技贸易职业学院单招职业适应性考试题库含答案详解(培优b卷)
- 2026年广东省珠海市单招职业适应性测试题库及答案详解(夺冠)
- 2026年张家界辅警笔试题库完整答案
- 高中生物遗传系谱图的编程可视化教学案例对比教学研究课题报告
- 数字化技术赋能供应链韧性增强的机制与路径分析
- 福建省漳州市2025-2026学年高三上学期期末教学质量检测化学试卷
- 2026年春苏教版新教材小学科学二年级下册教学计划及进度表
- 《做个“开心果”》-2025-2026学年统编版(新教材)小学道德与法治二年级下册
- 2025年电信客服服务规范与技巧
- 人工智能在智能家居应用
- 机制砂场生产管理制度
- 针灸安全规范管理制度
- 医疗设备采购与招标流程
评论
0/150
提交评论