您好,欢迎访问三七文档
第4章汇编程序举例4.4.2顺序程序•没有分支、没有循环、没有转移•[例4-16]对于三个8位无符号数86H、34H和21H,编写S=86H×34H-21H的程序。取被乘数求乘积取乘数取第三个数作操作数做减法结果送指定处结束初始化取被乘数求乘积取乘数取第三个数作操作数做减法结果送指定处NUMDB86H,34H,21HRESULTDW?SI作为数据区的指针;DI作为结果指针;•DATASEGMENT•NUMDB86H,34H,21H;定义源操作数•RESULTDW?;定义结果存放单元•DATAENDS•CODESEGMENT•ASSUMECS:CODE,DS:DATA•START:MOVAX,DATA•MOVDS,AX•LEASI,NUM•LEADI,RESULT•MOVAL,[SI]•MOVBL,[SI+1]•MULBL;求乘积•MOVBL,[SI+2];取第三个数作操作数•MOVBH,0•SUBAX,BX•MOV[DI],AX;结果送RESULT•MOVAH,4CH;返回DOS•INT21H•CODEENDS•ENDSTART[例4—17]内存自TABLE开始的连续16个单元中存放着0~15的平方值(称平方表),查表求DATA中任意数X(0≤X≤15)的平方值,并将结果放在RESULT中.DSEGSEGMENTTABLEDB0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225;定义平方表DATADB?RESULTDB?;定义结果存放单元DSEGENDSSSEGSEGMENTSTACK'STACK'STADW100DUP(?);定义堆栈空间TOPEQULENGTHSTASSEGENDS014916…TABLEBXCSEGSEGMENTASSUMECS:CSEG,DS:DSEG,SS:SSEGBEGIN:MOVAX,DSEG;初始化数据段MOVDS,AXMOVAX,SSEG;初始化堆栈MOVSS,AXMOVSP,TOP;置堆栈指针LEABX,TABLE;置数据指针MOVAH,0MOVAL,DATA;取待查数ADDBX,AX;查表MOVAL,[BX]MOVRESULT,AL;平方数存RESULTMOVAH,4CHINT21HCSEGENDSENDBEGIN4.4.3分支程序设计条件1成立?…条件2成立?条件n成立?Pn+1PnP2P1YYYNNN判定条件P1P2YN分支程序的基本结构(a)(b)•[例4-18]编写程序,将数据区中以字节变量BUFFER为首地址的100个单元清零。DATASEGMENTBUFFERDB100DUP(?)COUNTDB100;定义数据缓冲区长度DATAENDSSTACKSEGMENT‘STACK’DW32DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTART:MOVAX,DATAMOVDS,AX;初始化数据段MOVAX,STACKMOVSS,AX;初始化堆栈段MOVCL,COUNT;置单元长度MOVCH,0LEABX,BUFFERAGAIN:MOV[BX],0;实现100个单元清零INCBXINCCHCMPCH,CLJBAGAIN;CHCL则转移MOVAH,4CHINT21HCODEENDSENDSTARTDATASEGMENTBUFFERDB100DUP(?)DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVCX,100;置缓冲区长度LEABX,BUFFERAGAIN:MOV[BX],0INCBXLOOPAGAINMOVAH,4CHINT21HCODEENDSENDSTART[例4-19]在数据段DATA1开始的80个连续的存储单元中,存放80位同学某门课程的考试成绩(0~100)。编写程序统计成绩≥90分的人数,80~89分的人数,70~79分的人数,60~69分以及60分的人数。将结果存放到DATA2开始的存储单元中。DATASEGMENTDATA1DB80DUP(?);假定学生成绩已放入这80个单元中DATA2DB5DUP(0);统计结果的存放单元DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVCX,80;统计80个学生LEASI,DATA1LEADI,DATA2AGAIN:MOVAL,[SI];取一个学生成绩CMPAL,90;与90比较JCNEXT1;小于90分,转NEXT1INCBYTEPTR[DI];否则90分以上的人数加1JMPSTO;转循环控制处理NEXT1:CMPAL,80;与80比较JCNEXT2;小于80分,转NEXT2INCBYTEPTR[DI+1];否则80分以上的人数加1JMPSTONEXT2:CMPAL,70;与70比较JCNEXT3;小于70分,转NEXT3INCBYTEPTR[DI+2];否则70分以上的人数加1JMPSTONEXT3:CMPAL,60;与60比较JCNEXT4;小于60分,转NEXT4INCBYTEPTR[DI+3];否则60分以上的人数加1JMPSTO;转循环控制处理NEXT4NEXT4:INCBYTEPTR[DI+4];60分以下的人数加1STO:INCSI;指向下一个学生成绩LOOPAGAIN;循环,直到所有成绩都统计完MOVAH,4CH;返回DOSINT21HCODEENDSENDSTART4.4.4循环程序设计•循环程序设计结构初始化部分工作部分修改部分循环结束?结束部分初始化部分循环结束?工作部分修改部分结束部分先执行后判断先判断后执行[例4-20]把从MEM单元开始的l00个16位无符号数按从大到小的顺序排列。9124157129157412159741512974DSEGSEGMENTMEMDWl00DUP(?);假定要排序的数已DSEGENDS;存入这200个单元中CSEGSEGMENTASSUMECS:CSEG,DS:DSEGSTART:MOVAX,DSEGMOVDS,AXLEADI,MEM;DI指向MEM的首址MOVBL,99;外循环只需99次即可;外循环体从此开始NEXT1:MOVSI,DI;SI指向当前要比较的数MOVCL,BL;CL为内循环计数器,循环次数每次减l;以下为内循环NEXT2:MOVAX,[SI];取第一个数NiADDSI,2;指向下一个数Nj,CMPAX,[SI];比较Ni和NjJNCNEXT3;若Ni大于Nj,则不交换MOVDX,[SI];否则,交换Ni和NjMOV[SI-2],DXMOV[SI],AXNEXT3:DECCL;内循环结束?JNZNEXT2;若未结束,则继续;内循环到此结束DECBL;外循环结束?JNZNEXT1;若未结束,则继续;外循环体结束MOVAX,4C00H;返回DOSINT21HCSEGENDSENDSTART•[例如4-21]两个多字节二进制数求和程序;•DATASEGMENT•BUFF1DB4FH,0B6H,7CH,34H,56H,1FH•BUFF2DB13H,24H,57H,68H,0FDH,9AH•SUMDB6DUP(?)•COUNTDB3•DATAENDS•CODESEGMENT•ASSUMECS:CODE,DS:DATA•START:MOVAX,DATA•MOVDS,AX•MOVSI,OFFSETBUFF1•MOVDI,OFFSETBUFF2•MOVBX,OFFSETSUM•MOVCL,COUNT;初始化计数器•MOVCH,0•CLC;CF=0•GOON:MOVAX,[SI]•ADCAX,[DI]•INCSI•INCSI•INCDI•INCDI•MOV[BX],AX•INCBX•INCBX•LOOPGOON•MOVAH,4CH•INT21H•CODEENDS•ENDSTART4.4.5子程序设计•1、子程序的作用:•功能独立,可重复调用;便于程序设计模块化;•2、子程序说明:•①子程序名;•②子程序功能描述;•③子程序入口参数和出口参数;•④子程序中使用那些寄存器和存储单元;•⑤该子程序是否又调用其它子程序;•⑥子程序调用形式、举例;使用子程序的注意事项:参数传递寄存器传递参数,常用于参数较少的情况;堆栈传递,常用于子程序嵌套调用或递归调用;参数表传递,适用于参数较多的情况;变量、地址表等;•主程序现场保护:•常常是子程序用到的寄存器主程序也会用到,为了防止破坏主程序中寄存器的内容,需要在子程序入口处将其所用到的寄存器内容压栈保护。子程序部分•通常一个完整的子程序由下面五个部分组成:①子程序入口:通常用子程序名作为子程序入口,也就是标号地址。②保护现场:为了不破坏主程序原有信息,进入子程序首先把子程序中将要用到的寄存器、存储单元等压入堆栈或存入空存储单元中。③子程序体④恢复现场:把前边保护的现场信息进行恢复。⑤子程序返回:RET指令,返回到主程序的断点处,继续执行主程序。例一、编写一个将单字节的二进制数转换成BCD码数的程序,再将对应的十进制数位转换成ASCII码字符串,在显示器上显示出来。分析:设单字节二进制数存放在NUMBIN单元。利用除法实现转换。第一步,将该数除以100,商即为BCD码数的百位,保留第一步所得余数。第二步,将第一步所得余数再除以10,商即为BCD码数的十位,余数即为BCD码数的个位。第三步,将BCD码数的百位、十位和个位分别加上30H,即为它们的ASCII码。第四步,将ASCII码字符串存入一个缓冲区,再调用DOS功能调用INT21H的09H号功能,即可显示该字符串。DATASEGMENTNUMBINDB0E7H;待转换的单字节二进制数STRINGDB10DUP(20H);定义显示缓冲区DB0DH,0AH;定义回车换行符DB‘$’;定义结束符DATAENDSSTACKSEGMENTPARASTACK‘STACK’DB100DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTARTPROCFARBEGIN:PUSHDSMOVAX,0;返回DOS,同4C功能PUSHAXMOVAX,DATAMOVDS,AX;置段寄存器初值LEADI,STRINGXORAH,AH;AH清零MOVAL,NUMBINMOVBL,100DDIVBL;AX除以BL,商在AL中,余数在AH中CALLBCDTOASC;调用转换程序,入口参数:;AL=BCD数MOVAL,AH;取余数送ALXORAH,AHMOVBL,10DDIVBLCALLBCDTOASCMOVAL,AHCALLBCDTOASCCALLDISPASC;调用显示程序RETSTARTENDPBCDTOASCPROC;BCD码到ASCII码转换程序ADDAL,30HMOV[DI],AL;保存ASCII字符INCDI;指向下一个单元RETBCDTOASCENDPDISPASCPROC;显示子程序LEADX,STRINGMOVAH,09HINT21HRETDISPASCENDPCODEENDSENDBEGIN例二利用堆栈传递被加数和加数,在子程序中实现两个32位无符号数相加的过程,结果置于DX:AX中返回。DATASEGMENTNUM1DD01234567H;定义第一个32位数,存放顺序:67H,45H,23H,01HNUM2DD89ABCDEFH;定义第二个32位数,存放顺序0EFH,0CDH,0ABH,89HRESULTDD(?);定义结果单元DATAENDSSTACKSEGMENTPARASTACK'STACK'DB100DUP(?)STACKENDS;CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACK;STARTPROCFARBEGIN:PUSHDSMOVAX,0PUSHAXMOVAX,DATAMOVDS,AXMO
本文标题:汇编程序举例
链接地址:https://www.777doc.com/doc-2172391 .html