资源目录
压缩包内文档预览:
编号:21836146
类型:共享资源
大小:11.91MB
格式:ZIP
上传时间:2019-09-06
上传人:QQ24****1780
认证信息
个人认证
王**(实名认证)
浙江
IP属地:浙江
25
积分
- 关 键 词:
-
大学
汇编
语言程序设计
相伟
课件
ppt
- 资源描述:
-
大学汇编语言程序设计-相伟-课件PPT,大学,汇编,语言程序设计,相伟,课件,ppt
- 内容简介:
-
21世纪高等院校规划教材汇编语言程序设计相 伟 主编徐小平 李珍香 副主编中国水利水电出版社第5章 循环程序设计本章主要讲解循环程序的基本结构和设计方法。通过本章学习,读者应该掌握以下内容:循环程序的一般结构形式循环指令计数型循环与条件型循环单重循环程序设计方法多重循环程序设计方法5.1 循环程序的一般结构循环程序按照结构可分为单重循环和多重循环,按照循环控制的方法,可分为计数型循环与条件型循环。但是不管哪一种形式,循环程序都是由以下三部分组成:(1)循环初始化部分:为循环做准备工作,如设置循环次数,设置循环体需要的初始值以及控制循环的结束条件等。(2)循环体部分:这是循环工作的主体,是需要重复执行的部分。其中也包括对循环条件进行修改的程序段。如果循环体中不包括其它的循环程序,则为单重循环结构,否则称为多重循环结构。(3)循环控制部分:根据循环结束条件判断是否继续循环。在循环次数已知的情况下,可用循环次数作为循环结束的条件,后面介绍的LOOP指令使这种循环很容易实现,这种循环属计数型循环;但是当循环次数未知时,就必须根据具体情况选择合理的结束条件,保证程序正常退出循环,这种循环属条件型循环。以下的流程图很好地说明了这两种循环结构。图5-1所示为计数型循环,图5-2所示为条件型循环。实际应用中,我们可以将循环控制部分放在循环体之前进行,形成“先判断、后循环”的结构形式,也可以将循环控制部分放在循环体之后,形成“先循环、后判断”的结构形式。读者可以根据需要灵活掌握。下面分别举例说明计数型循环和条件型循环的控制方法。例5-1:已知有n 个8位有符号二进制数,存放在以BUF为首址的字节存储区中,试统计其中正数的个数。分析:每个元素是一个8位有符号二进制数,因此要判断其是否为正数,需选择带符号数条件转移指令进行判断转移。由于共有n个元素,因此整个程序的结构就是对以上判断重复n次,故选用计数型循环程序实现。存储单元及寄存器分配如下: BX:BUF存储区的地址指针,初值为BUF的偏移地 址,每循环一次之后,其值加1。 CX:循环计数器,初值为BUF存储区中元素的个数n, 每循环一次之后,其值减1。 AX:用来存放正数的个数,初值为零。 字变量COUNT:用来最终存放正数的个数。程序流程图如图5-3所示:源程序如下:STACK SEGMENT STACK DB 200 DUP(0)STACK ENDSDATA SEGMENTBUF DB 8,10,-5,100,-7,25,40N =$BUF ;BUF区中元素个数COUNT DW ?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXLEABX,BUFMOVCX,N ;循环初始部分MOVAX,0AGAIN:CMPBYTE PTR BX, 0JLENEXTINCAX ;循环体部分NEXT: INCBXDECCXJNZAGAIN ;控制部分MOVCOUNT,AX ;将正数个数送入COUNT中MOVAH,4CHINT21HCODEENDSENDBEGIN该程序的循环体被重复执行了n次,即当(CX)= n,n-1,1时循环执行,当(CX)= 0时结束循环,将正数个数5送入字变量COUNT中。对这种计数型循环,为了控制循环结束,在进入循环前要先确定循环次数,以后每循环一次就修改计数值,当计数值为零时就结束循环。读者可以思考以下问题:(1)在循环初始部分,如果将循环次数的负值送入循环计数器CX中,即“MOV CX ,n”,应该如何修改循环体部分和循环控制部分?(2)如果将0送入循环计数器CX中,即“MOV CX ,0”,应该如何修改程序呢?(3)如果要分别统计出正数、零、负数的个数,应如何设计程序?例5-2:统计寄存器BX中1的个数,结果存放在COUNT单元中。分析:要统计BX中1的个数必须进行逐位测试。首先判断最高位是否为1,然后用移位的方法把各位逐次移到最高位进行判断。循环的结束条件可用计数值16来控制,也就是可以用计数型循环来设计。但这种方法的缺点是无论BX中有没有1都必须循环16次。下面我们用条件控制法,即通过测试BX的值是否为零作为结束条件,这样可以大大缩短循环次数。存储单元及寄存器分配如下:BX:要测试的寄存器。CX:用来存放1的个数,初始值为0。字变量COUNT:用来最终存放1的个数。程序流程图如图5-4所示:源程序如下:STACKSEGMENTSTACK DB 200 DUP(0)STACKENDSDATASEGMENTCOUNTDW?DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVCX,0 ;CX0NEXT:ANDBX,BX ;测试BXJZEXIT ;(BX)= 0,结束循环转EXITJNSNEXT1 ;SF = 0转NEXT1INCCX ;否则CX (CX)+1NEXT1:SHLBX,1 ;(BX)左移1位JMPNEXT ;转NEXT继续循环EXIT: MOVCOUNT,CX ;COUNT1的个数MOVAH,4CHINT21HCODEENDSENDBEGIN本程序在运行前并不知道BX的值。若全为0,则不必循环,直接转EXIT结束程序。若只有最高位为1,则执行“INC CX”后,左移一位,再转NEXT处判断,此时(BX)=0转EXIT结束程序,仅需执行一次循环。只有最低位为1时才需通过16次执行循环体,统计出BX中的个数。显然,此处用条件控制循环效率最高。另外,本题在测试某位是否为1时,也可以将最高位左移,通过判断CF是否为1来实现。5.2 循环指令为了简化循环程序的设计,8086/8088专门设置了一组循环指令:LOOP、LOOPZ/LOOPE和LOOPNZ/LOOPNE。这些循环指令在执行前,必须预先将循环次数存放在CX寄存器中。另外这些循环控制指令只能实现短转移,即相对于当前IP值,转移范围为128 127个字节。循环执行均不影响状态标志位。下面分别介绍各条循环指令:1LOOP 循环指令格式:LOOP 标号功能: CX(CX)- 1 ; 判断CX的值,若(CX)0转移到标号处继续循环;否则退出循环。例5-3:计算1 + 2 + 3 + + 100,并将结果存入字变量SUM中。分析:这是一个典型的计数型循环用于求累加和问题。循环体执行次数已知(=100)。程序流程图如图5-5所示:存储单元及寄存器分配如下:AX:用来存放累加和,初值为0。CX:用来存放循环次数,初值为100,每次减1。SUM:用来存放最终结果的字变量。源程序如下:STACKSEGMENTSTACK DB200DUP(0)STACKENDSDATASEGMENTSUMDW?DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVAX,0;AX清零MOVCX,100;CX循环次数100NEXT:ADDAX,CX;求累加和LOOPNEXT;MOVSUM,AX;将累加和送入字变量SUM中MOVAH,4CHINT21HCODEENDS ENDBEGIN程序运行后,在字变量SUM中保存的值是5050。思考:(1)程序中“LOOP NEXT”语句可以用哪两条语句来代替?(2)若要求从1开始连续50个奇数的和,应如何编程?2LOOPZ/LOOPE为零或相等时循环指令。格式:LOOPZ/LOOPE 标号功能: CX (CX)-1 ; 判断CX和ZF值,若(CX)0且ZF = 1转移到标号处继续循环;若(CX)= 0或ZF = 0则退出循环。3LOOPNZ/LOOPNE不为零或不相等时循环指令格式:LOOPNZ/LOOPNE 标号功能: CX(CX)-1 ; 判断CX和ZF值,若(CX)0且ZF = 0转移到标号处继续循环;若(CX)= 0或ZF = 1则退出循环。LOOPZ/LOOPE和LOOPNZ/LOOPNE指令提供了提前结束循环的可能性。例5-4:已知在以BUF为首址的字节存储区中存放着一个有N个字符的字符串。试编写程序在字符串中查找第一次出现的字符“E”(ASCII码为45H)。若找到将其偏移位置存入FOUND单元;否则在屏幕上显示“NO FIND!”。分析:本题目要求在一字符串中查找某一字符,查找方法有多种,这里采用顺序查找方法。若找到将其偏移位置保存起来,结束程序;否则显示一提示信息。存储单元与寄存器分配如下:SI:BUF存储区中字符的偏移位置,初值为1,每次递增1。AL:用来保存要查找的字符。CX:来存放循环次数,初值为字符串长度,每次减1。BUF:用来存放字符串的存储区。FOUND:用来存放查找成功时字符的偏移位置。源程序如下:STACKSEGMENTSTACK DB 200DUP(0)STACKENDSDATASEGMENTBUFDBHELLO,MY FRIEND!N = $ - BUFFOUNDDW?NOFINDDB 0DH,0AH,NO FIND!$DATAENDSCODESEGMENT ASSUME CS:CODE,SS:STACK,DS:DATABEGIN:MOVAX,DATAMOVDS,AX MOVCX,N;CX 字符串长度N MOVSI,-1;初始化下标变量 MOVAL,45H;AL 要查找字符的ASCII码 NEXT:INCSICMPAL,BUFSI;判断是否是要找的字符LOOPNE NEXT;如果ZF=0且(CX) 0,则转NEXT继续循环JNZNO_FIND;如果ZF=0,则查找不成功,转NO_FINDMOV FOUND,SI ;如果ZF=1,查找成功,将偏移位置送给FOUND单元 JMP EXITNO_FIND: MOVDX,OFFSET NOFINDMOVAH,9;显示“NO FIND!”提示信息INT21HEXIT:MOVAH,4CHINT21H;程序结束CODEENDSENDBEGIN在程序执行过程中,有两种可能性:(1)在查找过程中成功找到字符“E”,此时ZF=1提前退出循环。执行JNZ指令时因不满足测试条件而执行指令“MOV FOUND,SI”。(2)一直查找到字符串结束而未发现字符“E”,则因(CX)= 0而结束循环。在执行JNZ指令时,因ZF=0而转NO_FIND去执行。5.3 循环程序设计方法循环程序按结构可分为单重循环程序和多重循环程序,下面分别进行介绍。5.3.1 单重循环程序设计 所谓单重循环,就是其循环体内不再包含循环结构的程序。例5-5:假设在以BUF为首址的存储单元中存放着一串字符,找出其中ASCII码最大的字符,并存入MAX单元中。分析:在一串字符中要寻找最大值,我们可以首先假设第一个字符就是最大字符,将其存入AL单元中。然后从第二个字符开始依次与AL比较,若某个字符比AL还大,则将其赋给AL,这样比较下去,最后在AL中保存的就是最大字符。存储单元与寄存器分配如下:CX:循环次数控制变量,初值为字符串的长度1,每次减1。BX:BUF存储区地址指针,初值指向BUF,每次加1。AL:用来求最大值的工作单元,保持某个时刻的最大值。MAX:用来保存最终结果的字节单元。程序流程图如图5-6所示:源程序如下:STACKSEGMENTSTACK DB200DUP(0)STACKENDSDATASEGMENTBUFDBABCD5678bdcaMNN = $ - BUFMAXDB?DATAENDCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVBX,OFFSETBUF;BX指向字符串首MOVAL,BX;取出第一个字符MOVCX,N-1;比较次数送CXNEXT1:INCBX;BX指向下一字符CMPAL,BX;比较JNCNEXT2MOVAL,BX;大数送ALNEXT2:LOOPNEXT1;循环次数(CX) 0继续循环MOVMAX,AL;MAX最大数MOVAH,4CHINT21H CODEENDSENDBEGIN程序运行后,在MAX单元中保存的字符是“d”。例5-6:试编制一个程序把NUM字存储单元中的二进制数用十六进制数的形式在屏幕上显示出来。分析:我们可以把NUM字单元中的内容从左到右每4位为一组,在屏幕上显示出来,这可以用循环结构实现,每次显示一个十六进制数,共循环4次。在循环体内完成把四位二进制数转换为一个十六进制数字的功能。这里采用循环移位的方法把要处理的四位二进制数移到最右端。然后进行数字到字符的转换工作。若是数字0 9,直接将其ASCII码加30H就转换成字符09;若是字母AF,除将其ASCII码加30H外,还应加上07进行调整,才能转换成AF。DI:用来指向保存转换结果的存储单元,每次加1。BX:用来保存要转换的二进制数的工作单元。CH:循环计数器,初值为4,每次减1。CL:循环移位次数,每次移4位。AL:转换中用到的工作单元。程序流程图如图5-7所示:源程序如下:DATASEGMENTNUMDW0010110100111001BBUFDB0AH,0DH,(NUM)= BUF0DB6 DUP(?)DATAENDSSTACKSEGMENT STACK DB200DUP(0)STACKENDS存储单元及寄存器分配如下:CODESEGMENT ASSUME CS:CODE,SS:STACK,DS:DATABEGIN:MOVAX,DATAMOVDS,AXMOVBX,NUM ;要转换的二进制数送入BXLEADI,BUF0 ;保存转换结果的存储单元首址送DIMOVCH,4 ;CH循环次数NEXT: MOVCL,4 ;CL循环移位次数ROLBX,CL ;每次将要处理的4位二进制数移到最低位MOVAL,BL ;取BX的低字节送ALANDAL,0FH ;取出最低4位ORAL,30H ;转换成十六进制CMPAL,3AHJLDONE ;9 时转移ADDAL,07H ;若大于加07调整DONE: MOVDI,AL ;将转换后的十六进制数送BUF0存储区保存INCDI ;指向下一存储单元DECCH ;CH (CH)1JNZNEXT ;若(CH) 0转NEXT继续转换MOVBYTE PTRDI,H;否则在转换完的十六进制数后加HINCDI ;MOVBYTE PTRDI,$LEADX,BUFMOVAH,9 INT21H MOVAH,4CHINT21HCODEENDS ENDBEGIN程序运行后,在屏幕上显示: (NUM)= 2D39H例5-7:已知在以BUF为首址的字节存储区中,存放着一个以$作为结束标志的字符串,试编写程序完成下列功能:统计其中小写字母的个数并存入COUNT单元中;在屏幕上显示该字符串,并要求将小写字母以大写字母形式显示出来。分析:本题目中没有直接给出字符串的长度,而是给出了字符串的结束标志。因此我们可以选用条件控制法来控制循环的执行。每当从存储区中取出一个字符后,首先判断是否是字符$,若是,则结束循环的执行。否则,判断是否为小写字母,若是,先将累加器加1,再将小写字母转换成大写字母(ASCII码减去20H)送显示器显示;若不是小写字母,则直接送显示器显示。程序流程图如图5-8所示:存储单元和寄存器分配如下: BX:指向BUF存储区的地址指针,每次加1。 AX:用来保存小写字母个数的工作单元。 DL:存放要显示字符的工作单元。 COUNT:用来最终保存小写字母个数的字变量单元。源程序如下:STACKSEGMENTSTACK DB200DUP(0)STACKENDSDATASEGMENTBUFDB This is a Assembly Program.$COUNT DW ?DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOV AX,0 ;AX清0LEABX,BUF ;BX BUF的偏移地址NEXT: MOVDL,BX ;从存储区中取一字符送入DL中CMPDL,$ ;若为结束标志$,则转EXITJEEXITCMPDL,aJBDONE ;若不是小写字母,则转DONE直接显示CMPDL,z JADONESUBDL,20H ;将小写字母转换成大写字母INCAX ;计数器加1DONE: MOVAH,2INT21HINCBX ;指向下一个字符,继续循环JMPNEXTEXIT: MOVCOUNT,AX ;循环结束,将小写字母个数写入COUNT单元MOVAH,4CHINT21HCODEENDSENDBEGIN程序运行后,COUNT单元中的内容为19(=13H)。屏幕上显示:THIS IS A ASSEMBLY PROGRAM下面我们再介绍一个用单重循环结构实现顺序查找的程序。例5-8:假设在以TAB为首址的字节存储区中,存放着n 个学生汇编语言的期末考试成绩。其中学号顺序是随机的。现需要在表中查找某个学号对应的汇编语言成绩,若查找成功,则将该学号的偏移地址送SI,对应成绩送DH寄存器,并将字节变量FLAG置1;否则将FLAG清0,表示查询失败。分析:要在一批数据中查找满足条件的值,最简单的办法就是采用顺序查找法。从第一个数据开始逐一进行比较。如果找到满足条件的值,就跳出循环,取出信息送入指定寄存器,并执行相应操作;否则顺序向下查找,如果查找遍所有n 个数据仍未找到,则结束循环,查找失败。具体实现时可在数据存储区中建一个表,表中每一项根据实际情况占若干字节,本例中对每个学生只有学号和成绩两个值,因此每项可占两个字节,有n 个学生,共占2n个字节。存储单元和寄存器分配如下:N:用来存放TAB表的总项数。CX:循环计数器,初值为N,每次减1。BX:指向表TAB的地址指针,每次增2。AL:用来存放要查找的学号。SI: 查找成功时用来保存学号的偏移地址。DH:查找成功时用来保存对应成绩信息。FLAG:标志变量,1表示查找成功,0表示失败。NUM:用来存放要查找的学号。程序流程图如图5-10所示:源程序如下:STACKSEGMENTSTACK DB 200 DUP(0)STACKENDSDATASEGMENTTAB DB 5,90,8,75,2,80,6,78,15,84,3,95,12,86,20,92N ($ TAB)2;表TAB中的总项数NUMDB6 ;要查找6号学生的成绩信息FLAGDB?DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXLEABX,TAB ;BXTAB的偏移地址MOVCX,N ;CXNMOVAL,NUM ;AL待查找的学号NEXT: CMPAL,BX JEDONE ;(AL)=(BX),查找成功转DONEADDBX,2 ;否则BX增2,指向下一项DECCX ;CX (CX)1JNENEXT ;(CX) 0,继续查找MOVFLAG,0 ;否则FLAG0,查找失败JMPEXITDONE: MOVSI,BX ;SI已找到学号在表中的偏移位置MOVDH,BX+1 ;DH对应的成绩MOVFLAG,1 ;FLAG1,表示查找成功EXIT: MOVAH,4CHINT21HCODEENDSENDBEGIN本程序运行后,有(SI)= 6,(DH)= 4EH,(FLAG)= 1读者可自己分析程序的执行过程。另外,还可思考以下几个问题: 若TAB表中除汇编成绩外,还有英语、数学两个成绩,每个数据项应分配几个字节?如何实现? 若要查找的学号不是在数据段中直接给出,而是需要在程序运行时通过键盘即时输入,应如何实现? 若查找成功时,要求把学号和成绩直接在屏幕上显示出来,应如何实现?以上通过几个例子介绍了单重循环程序的设计方法,若循环次数已知,可用计数型循环来实现,若循环次数未知,可通过条件型循环来控制。不论哪种形式,其循环体内都只有顺序结构和分支结构两种形式。但在实际应用中,我们还会碰到更复杂的循环体中又包含循环结构的情况,这种循环体中又包含循环结构的程序叫做多重循环程序。5.3.2 多重循环程序设计多重循环即循环体内又嵌套有循环。多重循环程序设计的基本思想和单重循环程序设计是一致的,但实现起来更复杂一些。应分别考虑各重循环的控制条件及其程序实现,相互之间不能混淆,即内外层循环必须是嵌套的形式,不能出现交叉。下面举例说明多重循环程序设计的方法和特点。例5-9:在以BUF为首址的字节存储区中存放有n个无符号数x1,x2, xn,现将它们按由大到小的顺序排列在BUF存储区中,试编程实现。分析:本例题是对n个数据进行排序问题。排序是计算机程序设计中的一种重要算法,关键值按从小到大排列称为升序,从大到小排列称为降序。排序的方法有很多,如选择排序、冒泡排序、插入排序、shell排序等等。下面我们首先介绍比较简单的选择排序。选择排序算法如下(按降序排列):若一组数据放在n个存储单元中,首先进行第一轮比较,将第一个存储单元中的数与其后n-1个存储单元中的数依次进行比较,若两个数不满足降序排列,则将两者交换,即总是将两数中的大数放在第一个存储单元中,这样经过n-1次比较后,n个数中的最大者就存入第一个存储单元之中,其中n-1次比较可以用一个计数型循环来控制;接着进行第二轮比较,将第二个存储单元中的数与其后的n-2个存储单元中的数依次比较,不满足降序则交换,这样经过n-2次比较后,n个数中的第二大者就存入第二个存储单元之中,如此重复下去,直到第n-1轮比较完成后,将n个数中的第(n-1)大者存入第n-1个存储单元,剩下第n个存储单元中的数据自然就是n个数中的最小者,这样经过n-1轮比较就可以实现n个数据由大到小降序排列。从第一轮到第n-1轮的控制又可以用一个计数型循环来实现。这样整个程序就可以用一个二重循环来控制实现。其中外循环用来控制是第几轮比较,即要找第几个位置上的最大值,内循环用来控制如何找到这个最大值。例如,有如下4个数据: 60 27 96 43现要将它们按从大到小的次序重新排列。4个数的排序需要经过3轮比较才能完成。第一轮:将第一个存储单元中的数据60作为最大值,依次与后面的数据比较,不满足降序则交换。经过三次比较最终求出第一个位置上的最大值96。第一次:60 279643 6027不需交换 第二次:96 276043 6043不需交换第二轮:求出第二个位置上的最大值60,需经过两次比较。第一次:96 602743 2743不需交换第三轮:求出第三个位置上的最大值43,只需经过一次比较。第一次:96 604327 2743进行交换 至此,4个数据已排成递减序列。本题
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

人人文库网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。