您好,欢迎访问三七文档
汇编语言程序设计第8章子程序设计教案第8章子程序设计8.1子程序定义8.2子程序设计8.3*子程序的嵌套和递归8.4子程序应用例子程序定义◆子程序(过程)是具有一定功能的一组指令集合,可以在需要时被一次或多次调用。◆调用子程序的程序,称为主程序;被调用的程序,称为子程序(过程)。◆8086/8088子程序(过程)结构定义的伪指令:定义子程序伪指令PROC结束子程序伪指令ENDP◆子程序调用指令CALL◆子程序返回指令RET子程序(过程)定义伪指令过程定义伪指令PROC格式:过程名PROC[NEAR/FAR](过程的类型:NEAR——段内过程,FAR——段间过程。)过程结束伪指令ENDP格式:过程名ENDP(PROC语句与对应的ENDP语句的过程名必须一致。)子程序调用指令子程序调用指令CALL格式:⑴直接调用:CALL过程名⑵段内(近)直接调用:CALLNEARPTR过程名⑶段间(远)直接调用:CALLFARPTR过程名⑷段内(近)间接调用:CALLWORDPTRsrc⑸段间(远)间接调用:CALLDWORDPTRdsrc操作:(1)先把返回地址压入堆栈保存:段内调用把IP压入堆栈;段间调用把CS和IP压入堆栈。(2)再转向被调过程:段内调用只设置IP,段间调用设置CS和IP。子程序返回指令RET格式:⑴返回:RET⑵返回并清栈:RETn;n是偶数个字节数操作:如果是段内过程,弹出IP;如果是段间过程,弹出IP和CS。如果是“RETn”,除弹出返回地址外,(SP)+n→SP。注意:子程序结束必须执行到RET指令。当执行到RET指令时,SP一定要指向保存的返回地址,保证能正确返回。子程序返回指令子程序的结构形式◆子程序(过程)结构必须在代码段结构内。段名SEGMENT........CALL子程序名;子程序调用........过程名PROC[NEAR/FAR];子程序定义........;子程序体........RET;子程序返回过程名ENDP;子程序定义结束........段名ENDS子程序定义和调用示例DATASEGMENT……DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATAMAIN:……CALLSUBACALLSUBBCALLFARPTRSUBACALLNEARPTRSUBB……MOVAX,4C00HINT21HSUBAPROC……RETSUBAENDPSUBBPROCFAR……RETSUBBENDPCODEENDSENDMAIN子程序设计要点◆子程序(过程)必须是具有一定功能的指令集合。◆子程序(过程)结构必须被正确定义。◆必须对子程序的设计给以文字说明。说明的内容:1.子程序名;2.子程序功能;3.入/出口参数及传送方式;4.子程序使用的寄存器和内存单元;5.应用示例。子程序设计例;P151~152,【例8.2】计算Cm=m!/(n!*(m-n)!)的值。;计算N!子程序sub1:sub1procmovax,1next:mulcxloopnextretsub1endpmovcx,msubcx,ncallsub1;(m-n)!xchgbx,axmovdx,0divbx;m!/n!/(m-n)!movans,ax………;数据段:mequ4nequ3ansdw?;主程序:………movcx,ncallsub1;n!movbx,axmovcx,mcallsub1;m!movdx,0divbx;m!/n!movbx,axn保存现场和恢复现场◆子程序可以被一次或多次调用,必须在子程序中有保护现场和恢复现场的处理环节。◆子程序一般是利用堆栈保护现场和恢复现场。◆子程序保护现场和恢复现场例——P155,【例8.6】:SUB1PROCPUSHBXPUSHCX;保护现场BX,CX……子程序体……POPCX;恢复现场BX,CXPOPBXRETSUB1ENDP子程序的参数传递1.寄存器传递参数用寄存器传递子程序入/出口参数。此方法最通用,但传递参数个数有限。2.存储单元传递参数用存储单元传递子程序入/出口参数。此方法使用在传递参数个数较多,并且数据是连续存放的(数据缓冲区)。3.堆栈传递参数表把传递的入口参数依次压入堆栈,然后调用子程序;子程序取堆栈中的参数表使用;返回时使用RETn指令,弹出堆栈中的入口参数表(n为入口参数表的字节数)。寄存器传递参数;P157~158,【例8.7】统计字节数据区中0的个数。arraybdb45,23,90,125,………countequ$-arraybansdw?;主程序:………leasi,arraybmovcx,countcallznummovans,axMOVAX,4C00HINT21H;统计零个数子程序znum:zmunprocxorax,axnext:cmpbypeptr[si],0jnznzincaxnz:incsiloopnextretznumendp存储单元传递参数;P159~160,【例8.8】统计字节数据区中0的个数。;增加数据定义:para1dw?para2dw?para3dw?;主程序:………leasi,arraybmovpara1,simovpara2,countcallznummovax,para3movans,ax………;统计零个数子程序znum:zmunprocmovsi,para1movcx,para2xorax,axnext:cmpbypeptr[si],0jnznzincaxnz:incsiloopnextmovpara3,axretznumendp堆栈传递参数;P160~161,【例8.9】统计字节数据区中0的个数。arraybdb45,23,90,125,………countequ$-arraybansdw?;主程序:………leasi,arraybmovcx,countpushsipushcxcallznumpopaxmovans,ax………;统计零个数子程序znum:zmunprocmovbp,spmovsi,[bp+4]movcx,[bp+2]xorax,axnext:cmpbypeptr[si],0jnznzincaxnz:incsiloopnextmov[bp+4],axret2znumendp子程序的嵌套调用子程序的嵌套调用是指在被调子程序中又调用了其他子程序。嵌套可以达到多层。SUB0PROCSUB1PROCSUB2PROCCALLSUB1CALLSUB2S0:S1:RETRETRET子程序嵌套调用示意图子程序的递归调用子程序的递归调用是指在被调子程序中直接或间接的调用了自身。SUB0PROCSUB1PROCSUB2PROCCALLSUB0CALLSUB2CALLSUB1S0:S1:RETRETRET直接递归调用间递归调用子程序递归例;P167,【例8.11】递归计算N!。;数据段:NDW?;N≤8ANSDW?;主程序段:………MOVAX,NCALLFACTMOVANS,AX………;递归子程序fact:factprocpushdxmovdx,axcmpax,0jzfrdecaxcallfact;(n-1)!muldxpopdxretfr:movax,1;1!popdxretfactendp;求一个无符号字变量的10#(或2#,或16#)数位之和。;内存数据:Ndw?Sdw?;主程序段:……(读一个数,存入N单元)movax,n;ax取数nmovcx,10;cx取数制(或movcx,2)(或movcx,16)callsubr;ax,cx入口参数,bx出口参数movs,bx(输出位数之和S单元的值)……;求数位之和子程序subrsubrprocnearpushdx;保护现场movbx,0;数位和初值0→bxlop:cmpax,0jzok;ax=0,结束求数位和movdx,0divcx;除以10/2/16addbx,dxjmplopok:popdx;恢复现场retsubrendp子程序应用例习题8.3(1)8.3(1)从一个字符串中去除数字字符。(程序执行后,strd存储区内容为‘STRING’);数据段:strsdb‘S12TR4IN63G$’;存放源字符串countequ$-strsstrddbcountdup(?);主程序段:………leasi,strsleadi,strdcldnext:lodsbcmpal,'$'jzexitcalljugjncnextstosbjmpnextexit:movax,4c00hint21h;去除0~9数字子程序jug:jugproccmpal,'0'jbcharcmpal,'9'jacharclcretchar:stcretjugendp8.3(2)计算Y=3X4+X2-4X。xdb3ydw?………moval,x;al=3callfx;ax=38movdx,ax;dx=38moval,x;al=3imulal;al=9callfx;ax=278subax,dx;ax=240movy,ax;y=240………;计算(3X+4)X-1子程序jug:fxprocpushdxmovdl,al;dl=xmoval,3imuldl;ax=3xaddax,4;ax=3x+4xchgax,dx;dx=3x+4,al=xcbw;ax=ximuldx;ax=(3x+4)xdecax;ax=(3x+4)x-1popdxretfxendp习题8.3(2)8.4将一个字节2#数字转换成ASCII码数符。;堆栈传递3个参数:字节数,存放ASCII码地址,位数n。bindb11100011B;一个字节数(0E3H)ascbdb8dup(?);存放8个ASCII码值(31H/30H);主程序:……movah,bin;取bin字节数pushax;压入堆栈(1)leadi,ascb;取ascb偏移址pushdi;压入堆栈(2)movax,8;取位数8pushax;压入堆栈(3)callbtoa;调用btoa子程序……习题8.4;转换成ASCII码子程序btoa:btoaproc……;保护现场寄存器di,cx,dxmovbp,spmovcx,[bp+8];取位数8movdi,[bp+10];取ascb地址movdx,[bp+12];取bin字节数next:roldx,1moval,dlandal,1addal,30h;转换成ASCII码值mov[di],al;存放到ascb数据区incdiloopnext……;恢复现场寄存器di,cx,dxret6;返回,弹掉3个入口参数btoaendp
本文标题:8-子程序
链接地址:https://www.777doc.com/doc-3382657 .html