汇编语言第六章子程序结构.ppt_第1页
汇编语言第六章子程序结构.ppt_第2页
汇编语言第六章子程序结构.ppt_第3页
汇编语言第六章子程序结构.ppt_第4页
汇编语言第六章子程序结构.ppt_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

在程序设计中,可以发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。调用子程序的程序称为主调程序或主程序。,第6章子程序结构,子程序的基本结构包括以下几个部分:(1)子程序定义(2)保护现场和恢复现场(3)子程序体(4)子程序返回,子程序的结构,子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下:过程名PROCNEAR/FAR过程名ENDP其中PROC表示过程定义开始,ENDP表示过程定义结束。过程名是过程入口地址的符号表示。一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性(NEAR和FAR)。,6.1.1子程序的定义,6.1子程序的设计方法,1.如果调用程序和过程在同一代码段中,则使用NEAR属性;,MAINPROCFARCALLSUBR1RETMAINENDP;SUBR1PROCNEARRETSUBR1ENDP,MAINPROCFARCALLSUBR1RETSUBR1PROCNEARRETSUBR1ENDPMAINENDP,例6.1,过程嵌套定义,2.如果调用程序和过程不在同一代码段中,则使用FAR属性;,SEGXSEGMENTSUBTPROCFARRETSUBTENDPCALLSUBTSEGXENDS;SEGYSEGMENTCALLSUBTSEGYENDS,例6.2,6.1.2子程序的调用和返回,调用:CALLfar/nearptr过程名,返回:RETn,6.1.3保护现场和恢复现场,例如:若子程序PROG中改变了寄存器AX,BX,CX,DX的值,则可采用如下方法保护和恢复现场。PROGPROCPUSHAXPUSHBXPUSHCX;保护现场PUSHDXPOPDXPOPCXPOPBX;恢复现场POPAXRET;返回断点处PROCENDP,6.1.4主程序与子程序参数传递方式,1通过寄存器传送参数这是最常用的一种方式,使用方便,但参数很多时不能使用这种方法。例6.3十进制到十六进制转换的程序。程序要求从键盘取得一个十进制数,然后把该数以十六进制的形式在屏幕上显示出来。,开始,调用DECIBIN,调用CRLF,调用BINIHEX,调用CRLF,结束,从键盘取得十进制数,保存到BX中,显示回车和换行,用十六进制形式显示BX中的数,Decihexsegmentassumecs:DecihexMainprocfarRepeat:pushdsxorax,axpushaxcalldecibincallcrlfcallbinihexcallcrlfretMainendp,Decibinprocnearmovbx,0Newchar:movah,1int21hsubal,30hjlexitcmpal,9jgexitcbwxchgax,bxmovcx,10mulcxxchgax,bx;每次乘的addbx,ax;结果在BX中jmpnewcharExit:retDecibinendp,Binihexprocnearmovch,4Rotate:movcl,4rolbx,clmovdl,blanddl,0fhadddl,30hcmpdl,3ahjlprintadddl,7hPrint:movah,2int21hdecchjnzrotateretBinihexendp,Crlfprocnearmovah,2movdl,odhint21hmovdl,oahint21hretCrlfendpDecihexendsendrepeat,如果过程和调用过程在同一源文件(同一模块)中,则过程可直接访问模块中的变量。例6.4_1主程序MAIN和过程PROADD在同一源文件中,要求用过程PROADD累加数组的所有元素,并把和(不考虑溢出的可能性)送到指定的存储单元中去,DATASEGMENTARYDW100DUP(?)COUNTDW100SUMDW?DATAENDSCODESEGMENTMAINPROCFARASSUMECS:CODE,DS:DATASTART:PUSHDSSUBAX,AXPUSHAXMOVAX,DATACALLNEARPTRPROADDRETMAINENDP,PROADDPROCNEARPUSHAXPUSHCXPUSHSIPUSHDILEASI,ARYMOVCX,COUNTXORAX,AXNEXT:ADDAX,SIADDSI,2LOOPNEXTMOVSUM,AXPOPDIPOPSIPOPCXPOPAXRETPROADDENDPCODEENDSENDSTART,CODESEGMENTARYDW100DUP(?)COUNTDW100SUMDW?NUMDW100DUP(?)NDW100TOTALDW?MOVTABLE,OFFSETARYMOVTABLE+2,OFFSETCOUNTMOVTABLE+4,OFFSETSUNMOVBX,OFFSETTABLECALLPROADD;计算SUM,PROADDPROCNEARPUSHAXPUSHCXPUSHSIPUSHDIPUSHSI,BXMOVDI,BX+2MOVCX,DIMOVDI,BX+4XORAX,AXNEXT:ADDAX,SIADDSI,2LOOPNEXTMOV【DI,AXPOPDIPOPSIPOPCXPOPAXRETPROADDENDPCODEENDSENDSTART,3通过地址表传递参数,例6.4_2,4通过堆栈传递地址或参数,DatasegmentArydw100dup(?)Countdb100Sumdw?DataendsStacksegmentparastackstackdw100dup(?)toslabelwordStackendsCode1segmentassumecs:code1,ds:data,ss;stackMainprocfarStart:pushdsxorax,axpushaxmovax,datamovds,ax,movax,stackmovss,axmovsp,offsettosMovbx,offsetaryPushbxMovbx,offsetcountPushbxMovbx,offsetsumPushbxCallfarptrproaddmoval,summovdl,almovah,2int21hretMainendpCode1ends,例6.4_3,Sum地址Count地址Ary地址,sp,disicxaxbp,(Sp)bp,IPCS,Code2segmentassumecs:code2Proaddprocfarpushbpmovbp,sppushaxpushcxpushsipushdimovsi,bp+0ahmovdi,bp+08hmovcl,dimovdi,bp+06hxoral,alAgain:addal,siincsideccljnzagainmovdi,alpopdipopsipopcx,popaxpopbpret6ProaddendpCode2endsendstart,bp+0ah,bp+08h,bp+06h,Sp,Sp,Sp,Sp,Sp,(1)PUBLIC伪指令格式:PUBLIC符号,符号功能:说明其后的符号是全局符号。全局符号能被其他模块引用。(局部符号)(2)EXTRN伪指令格式:EXTRN符号:类型,符号:类型功能:说明在本模块中需要引用的、由其他模块定义的符号,即外部符号。,5多个模块之间的参数传送问题,;sourcemodule1extrnvar2:word,lab2:farpublicvar1,lab1Data1segmentvar1db?var3dw?var4dw?Data1endscode1segmentassumecs:code1,ds:data1Mainprocfarstart:movax,data1movds,axlab1:movah,4chint21hMainendpCode1endsEndstart,;sourcemodule2externvar1:byte,var4:wordpublicvar2Data2segmentvar2dw?var3dw?Data2endscode2segmentassumecs:code2,ds:data2Mainprocfarstart:movax,data2movds,axmovah,4chint21hMainendpCode2endsEndstart,注意:应先有public定义,然后才有extrn说明,;sourcemodule3externlab2:farpubliclab2,lab3Data2segmentvar2dw?var3dw?Data2endscode3segmentassumecs:code3Lab2:.Lab3:.Code3endsEnd,例6.5多个模块间的参数共享,;Sourcemodel1EXTERNproadd:farDATASEGMENTcommonARYDW100DUP(?)COUNTDW100SUMDW?DATAENDSCODE1SEGMENTMAINPROCFARASSUMECS:CODE1,DS:DATASTART:PUSHDSSUBAX,AXPUSHAXMOVAX,DATACALLfarptrPROADDRETMAINENDPCODE1ENDSENDSTART,主程序和子过程不在同一个模块的时参数传递方法一,LOOPNEXT:MOVSUM,AXPOPDIPOPSIPOPCXPOPAXRETPROADDENDPCODE2endsEND,;Sourcemodel2PUBLICPROADDDATASEGMENTcommonARYDW100DUP(?)COUNTDW100SUMDW?DATAENDSCODE2SEGMENTPROADDPROCFARASSUMECS:CODE2,DS:DATAMOVAX,DATAMOVDS,AXPUSHAXPUSHCXPUSHSIPUSHDILEASI,ARYMOVCX,COUNTXORAX,AXNEXT:ADDAX,SIADDSI,2,(如例6.4_1的参数传递可利用段覆盖),;Sourcemodel1externvar1:wordexternoutput:farexternvar2:wordpublicquitlocal_datasegmentvardw5local_dataendscodesegmentassumecs:code,ds:local_datamainprocfarstart:movax,local_datamovds,axmovbx,varmovax,segvar1moves,axaddbx,es:var1,主程序和子过程不在同一个模块的时参数传递方法二,movax,segvar2moves,axsubes:var2,50jmpouputquit:movah,4chint21hmainendpcodeendsendstart;Sourcemodel2publicvar1extdata1segmentvar1dw10extdata1endsend,;sourcemodel3publicvar2externquit:farextdata2segmentvar2dw3extdata2endspublicoutputprogramsegmentassumecs:program,ds:extdata2output:jmpquitprogramendsend,(例6.6含三个源模块),;Sourcemodel1GlobalsegmentpublicExternvar1:wordExternvar2:wordGlobalendsLocal_datasegmentLocal_dataendscodesegmentassumecs:code,ds:local_data,es:globalmainprocfar,主程序和子过程不在同一个模块的时参数传递方法三,start:movx,local_datamovds,axmovax,globalmoves,axmovbx,es:var1addes:var2,bxmovah,4chint21hmainendpcodeendsendstart,(例6.7含二个源模块),;sourcemodel2Globalsegmentpublicpublicvar1publicvar2var1dw?var2dw?Globalendsend,6.1.5增强功能的过程定义伪操作,ProcnamePROCattributesfieldUSERregisterlist,parameterfieldProcnameENDPAttributesfield(属性字段)包括:Distance:near、farLanguagetype:说明是那种高级语言的子程序如pascal、c等。Visibility:说明程序的可见性是private或是public。Prologue:是一个宏的名字,允许用宏来控制过程的入口或出口有关的代码USER:该字段用来指定用户所需保存和恢复的寄存器表。Parameterfield:参数字段,允许用户指定该过程所用的参数。标识符:类型,标识符:类型,DatasegmentArydb10dup(?)Countdb10Sumdb?DataendsStacksegmentparastackstackdb100dup(?)StackendsCode1segmentassumecs:code1,ds:data,ss:stackMainprocfarStart:pushdsxorax,axpushaxmovax,datamovds,ax,Movbx,offsetaryPushbxMovbx,offsetcountPushbxMovbx,offsetsumPushbxCallfarptrproaddmoval,summovdl,almovah,2int21hretMainendpCode1ends,对例6.4采用用增强功能过程定义伪操作实现,Code2segmentassumecs:code2Proaddprocfarpushbpmovbp,sppushaxpushcxpushsipushdimovsi,bp+0ahmovdi,bp+08hmovcl,dimovdi,bp+06hxoral,alAgain:addal,siincsideccljnzagainmovdi,alpopdipopsipopcxpopaxpopbpret6ProaddendpCode2endsendstart,Code2segmentassumecs:code2Proaddprocpascaluseraxcxsidi,para:word,parc:word,pars:wordmovsi,paramovdi,parcmovcl,dimovdi,parsxoral,alAgain:addal,siincsideccljnzagainmovdi,alretProaddendpCode2endsendstart,Sum地址Count地址Ary地址,(bp),IPCS,(bp+2),(bp+4),(bp+6),(bp+8),(bp+a),原始bp,pars,para,parc,局部变量,disicxax,(bp-2),Code2segmentassumecs:code2Proaddprocfarpushbpmovbp,sppushaxpushcxpushsipushdimovsi,bp+0ahmovdi,bp+08hmovcl,dimovdi,bp+06hxoral,alAgain:addal,siincsideccljnzagainmovdi,alpopdipopsipopcxpopaxpopbpret6ProaddendpCode2endsendstart,Code2segmentassumecs:code2ProaddprocCuseraxcxsidi,pars:word,parc:word,para:wordmovsi,paramovdi,parcmovcl,dimovdi,parsxoral,alAgain:addal,siincsideccljnzagainmovdi,alretProaddendpCode2endsendstart,Sum地址Count地址Ary地址,(bp),IPCS,(bp+2),(bp+4),(bp+6),(bp+8),(bp+a),原始bp,pars,para,parc,局部变量,disicxax,(bp-2),增强功能的过程定义伪操作除了以上功能外,还可以在过程中定义局部变量。局部变量是在过程内部使用的变量,他是在过程调用是在堆栈中建立的,在退出过程是被释放。可以用LOCAL定义LOCAL变量:类型,变量:类型,Sum地址Count地址Ary地址,(bp),IPCS,(bp+2),(bp+4),(bp+6),(bp+8),(bp+a),原始bp,(bp-2),(bp-4),局部变量,例6.8编程把以ASCII形式表示的十进制数转换为二进制数,.modelsmall.386.stack200h.dataAscvaldb12345Binvaldw?.codeMainprocfarStart:movax,datamovds,ax,leabx,asvalpushbxleabx,binvalpushbxcallconvaxbinmovah,4chint21hMainendp,Convascbinprocpascalusesax,bx,cx,dx,si,di,par1:word,par2:wordLocalasclen:word,mulfact:wordmovbx,10movsi,par1movdi,par2subdi,simovasclen,dimovcx,asclenaddsi,asclendecsimovmulfact,1movdi,par2movdi,0Next:moval,siandax,000fh,MulmulfactAdddi,axMovax,mulfactMulbxMovmulfact,axDecsiLoopnextRetConvascbinendpendmain,pushbpmovbp,spaddsp,0fchpushaxpushbxpushcxpushdxpushsipushdimovbx,oahmovsi,bp+6movdi,bp+4subdi,simovbp2】,dimovcx,bp-2addsi,bp-2decsimovwordptrbp-2,0001movdi,bp+4movwordptrdi,0,例6.8经过汇编后的Convascbin子过程程序,next:moval,siandax,000fhmulwordptrbp-4adddi,axmovax,bp-4mulbxmovbp-4,axdecsiloopnextpopdipopsipopdxpopcxpopbxpopaxmovsp,bppopbpret0004,6.2子程序的嵌套一个子程序可以作为调用程序去掉用另一个子程序,这种情况称为子程序的嵌套。嵌套深度不限。但应注意的问题是堆栈的溢出:上溢、下溢递归子程序:如果一个子程序调用的是子程序的本身,就是递归子程序。,例计算N!=N*(N-1)*(N-2)*1-递归子程序,DatasegmentNumdb3Resultdw?DataendsStacksegmentparastackstackdb100dup(?)toslabelwordStackendsCodesegmentassumecs:code,ds:data,ss:stackMainprocfarBegin:pushdsxorax,axpushaxmovax,datamovds,ax,movax,stackmovss,axmovsp,offsettosmovah,0moval,numcallfactormovresult,axretMainendp,Factorprocpushaxsubax,1jnef_contpopaxjmpreturnf_cont:callfactorpopcxmulclreturn:retfactorendpCodeendsendbegin,IP1,Movresult,ax地址,3,IP2,Popcx地址,2,IP3,Popcx地址,1,ax=1,IPPOPCX地址,cx=2,ax*cx=1*2,IPPOPCX地址,cx=3,ax*cx=1*2*3,IPMovresult,ax地址,常用的DOS系统功能调用,1单字符输入(1号调用)2单字符显示(2号调用)3打印输出(5号调用)4结束调用(4CH号调用)5显示字符串(9号调用)6字符串输入(10号调用),1单字符输入(1号调用)格式:MOVAH,1INT21H功能:从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。2单字符显示(2号调用)格式:MOVDL,待显示字符的ASCII码MOVAH,2INT21H功能:将DL寄存器中的字符送显示器显示.,3打印输出(5号调用)格式:MOVDL,待打印字符的ASCII码MOVAH,5INT21H功能:将DL寄存器中的字符送打印机打印。4结束调用(4CH号调用)格式:MOVAH,4CHINT21H功能:终止当前程序并返回调用程序。,5显示字符串(9号调用)格式:LEADX,待显示字符串首偏移地址MOVAH,9INT21H功能:将当前数据区中以结尾的字符串送显示器显示。6字符串输入(10号调用)格式:LEADX,缓冲区首偏移地址MOVAH,10INT21H功能:从键盘上输入一字符串到用户定义的输入缓冲区中,并送显示器显示。,maxlendb32actlendb?stringdb32dup(?),leadx,maxlenmovah,0ahint21h,说明:缓冲区的第一个字节保存最大字符数,这个最大字符数由用户程序给出。如果键入的字符数比此数大,机器发出嘟嘟声。第二个字节存放实际输入的字节数,这个不是由用户填入的而由功能A填入的。在这两个字节之后,才是我们输入的字符串。,6.3子程序举例,例1:HEXIDEX是一个十六进制数转换成十进制数的程序。要求把从键盘输入的0FFFFH的十六进制正数转换为十进制数并在屏幕上显示出来。,Displayequ2hKeyequ1hDoscallequ21hHexidecsegmentMainprocfarassumecs:hexidecStart:pushdssubax,axpushaxcallhexideccallcrlfcallbinideccallcrlfjmpmainretmainendp,Crlfprocnearmovdl,0ahmovah,displayintboscallmovdl,0dhmovah,displayintdoscallretcrlfendpHexidecendsendstart,Hexidecprocnearmovbx,0Newchar:movkey_inintdoscallsubal,30hjlexitcmpal,10djladd_tosubal,27hcmpal,0ahjlexitcmpah,10hjgeexitAdd_to:movcl,4shlbx,clmovah,0addbx,axjmpExit:RetHexidecendp,Binidecprocnearmovcx,10000dcalldec_divmovcx,1000dcalldec_divmovcx,100dcalldec_divmovcx,10dcalldec_divmovcx,1dcalldec_divretDec_divprocnearmovax,bxmovdx,0divcxmovbx,dxmovdl,aladddl,30hmovah,displayintdoscall,retdec_divendpBinidecendp,例2:一个简单的信息检索系统。在数据区里,有10个不同的信息,编号为09,每个信息包括30个字符。现在要编制一个程序:从键盘接收09之间的一个编号,然后在屏幕上显示相应编号的信息的内容。,Datareasegmentthirtydb30msg0db0IlikemyIBM-PC-msg1db1IlikemyIBM-PC-msg2db2IlikemyIBM-PC-msg3db3IlikemyIBM-PC-msg4db4IlikemyIBM-PC-msg5db5IlikemyIBM-PC-msg6db6IlikemyIBM-PC-msg7db7IlikemyIBM-PC-msg8db8IlikemyIBM-PC-msg9db9IlikemyIBM-PC-errmsgdberror!InvalidpraameterDatareaends,Stacksegmentdb256dup(0)toslablewordStackendsPrognamsegmentassumecs:prognam,ds:datarea,ss:stackStart:pushdsxorax,axpushaxmovax,stackmovss,axmovax,datareamovds,axmovsp,offsettosBegin:movah,1int21hsubal,0jcerrorcmpal,9jaerror,Movbx,offsetmsg0MulthirtyAddbx,axCalldisplayJmpbeginError:movbx,offseterrmsgcalldisplayretDisplayprocnearmovcx,30movdl,bxcalldispcharincbxloopdisp1movdl,0dhcalldispcharmovdl,0ahcalldispcharretDispcharendp,Dispcharprocnaermovah,2int21hretDispcharendpMainendpPrognamendsEndstart,例3:人名排序程序。先从终端键入最多30个人名,当所有人名都进入后,按字母上升的次序将人名排序,并在屏幕上显示已经排好的人名。,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论