您好,欢迎访问三七文档
汇编语言程序设计第六章子程序设计1、子程序的设计方法2、子程序的嵌套3、子程序应用举例汇编语言程序设计子程序的设计方法1、子程序的定义2、子程序的调用与返回指令3、保存与恢复寄存器4、子程序的参数传递汇编语言程序设计子程序的定义将一些常用的具有通用功能的操作编写成子程序,便于一个或多个程序使用,使程序设计模块化,从而达到代码复用、简化编程的目的。子程序定义伪指令:子程序名PROC[NEAR/FAR]子程序体RET子程序名ENDP其中:PROC表示子程序开始,ENDP表示子程序结束。过程名是子程序的入口地址,在程序中是唯一的。它应满足标识符的命名规则。FAR或NEAR是子程序的属性操作符,缺省时为NEAR属性。汇编语言程序设计NEAR的用法汇编语言程序设计FAR的用法汇编语言程序设计需要注意的问题1、在子程序体内,必须保证有一条RET指令被执行。如:PROC1PROCMOVAX,0PROC1ENDPPROC2PROCMOVBX,-1RETPROC2ENDP当用指令CALLPROC1调用子程序PROC1时,程序执行完PROC1后,直接顺序执行子程序PROC2,当执行到RET时才返回。汇编程序不会在PROC1的ENDP伪指令处返回主程序。2、当调用程序和子程序在同一个程序段时,属性选择NEAR,当调用程序和子程序不在同一个程序段时,属性应选择FAR。汇编语言程序设计子程序的调用与返回指令子程序的调用指令指令格式:CALLDST其中:目的操作数DST是子程序名或子程序首地址,可以是与转移指令有关的四种转移的寻址方式之一,即:段内直接调用、段内间接调用、段间直接调用、段间间接调用。如果目的操作数DST是子程序名(子程序首地址)或是转移地址,该有效地址直接出现在CALL指令中,则为直接调用;如果有效地址是在寄存器或存储器中间接得到的,则为间接调用。汇编语言程序设计CALL指令的格式段内直接近调用1、CALL子程序名2、CALLNEARPTR子程序名段内间接近调用3、CALL寄存器操作数4、CALLWORDPTR存储器操作数段间直接远调用5、CALLFARPTR子程序名段间间接远调用6、CALLDWORDPTR存储器操作数汇编语言程序设计CALL指令的格式1)段内直接调用SP=SP-2;SS:[SP]CALL指令的下一条指令的偏移地址IP=IP+D16(当DST为16位)2)段内间接调用SP=SP-2;SS:[SP]CALL指令的下一条指令的偏移地址IP=DST中的有效地址EA(当DST为16位)汇编语言程序设计子程序的调用指令3)段间直接调用SP=SP-2;SS:[SP]返回地址的段地址SP=SP-2;SS:[SP]返回地址的偏移地址IP=DST的偏移地址CS=DST的段地址汇编语言程序设计子程序的调用指令4)段间间接调用SP=SP-2;SS:[SP]返回地址的段地址SP=SP-2;SS:[SP]返回地址的偏移地址IP=EA的低16位CS=EA的高16位汇编语言程序设计子程序的返回指令指令格式:RET指令功能:段内返回:取栈顶的两字节内容送IP寄存器。段间返回:将堆栈中保存的IP和CS值分别送IP和CS寄存器。带立即数的返回指令:RETNN一般为偶数;该指令除了执行RET指令的功能外还要修改SP的值即:SP=SP+N汇编语言程序设计指令总结指令格式指令功能寻址方式CALLDSTCALLNEARPTRDSTSP=SP-2;SS:[SP]←CALL指令的下一条指令的IP值IP=IP+D16(当DST为16位)段内直接调用CALLFARPTRDSTSP=SP-2;SS:[SP]←返回地址的段地址SP=SP-2;SS:[SP]←返回地址的偏移值IP=DST的偏移地址,CS=DST的段地址段间直接调用CALL寄存器操作数如:CALLBXCALLWORDPTRMSP=SP-2;SS:[SP]←CALL指令的下一条指令的IP值IP=DST中的有效地址EA(当DST为16位)(IP←BX的值)段内间接调用CALLDWORDPTRDST如:CALLDWORDPTR[BX]SP=SP-2;SS:[SP]←返回地址的段地址SP=SP-2;SS:[SP]←返回地址的偏移值IP=EA的低16位,CS=EA的高16位(IP←DS:[BX]的值,CS←DS:[BX+2]的值)段间间接调用RETIP←SS:[SP],SP=SP+2段内返回RETIP←[SP],SP=SP+2CS←[SP],SP=SP+2段间返回RETNIP←[SP],SP=SP+2(段内)CS←[SP],SP=SP+2(段间)SP←SP+n段内或段间带参数调用汇编语言程序设计例子1、分析下列程序段,回答指定问题。10A3H:2000HXORAL,AL10A3H:2002HMOVAX,CS10A3H:2004HMOVSS,AX10A3H:2006HMOVSP,2F00H10A3H:2009HMOVDX,2012H10A3H:200CHPUSHDX10A3H:200DHCALL2700H10A3H:2010HADDCX,DX10A3H:2012HHLT10A3H:2700HPOPCXRET执行后(AX)=?(SP)=?(DX)=?(CX)=?ZF=?汇编语言程序设计答案分析下列程序段,回答指定问题。10A3H:2000HXORAL,AL10A3H:2002HMOVAX,CS10A3H:2004HMOVSS,AX10A3H:2006HMOVSP,2F00H10A3H:2009HMOVDX,2012H10A3H:200CHPUSHDX10A3H:200DHCALL2700H10A3H:2010HADDCX,DX10A3H:2012HHLT10A3H:2700HPOPCXRET执行后(AX)=10A3H(SP)=2F00H(DX)=2012H(CX)=2010HZF=1汇编语言程序设计保存与恢复寄存器子程序中需要使用的寄存器,有可能在主程序中正被用来保存某种中间结果,这些寄存器的值在从子程序返回主程序后还要继续使用,这些寄存器的值或所需的标志位的值等信息称之为现场。显然,子程序执行前需要保护现场,返回时要恢复现场。汇编语言程序设计保存与恢复寄存器保存现场与恢复现场的工作既可在调用程序中完成,也可在子程序中完成,程序设计时根据情况安排。如果子程序已经设计好了,而其中未保护主程序现场,那么调用程序在使用子程序之前应保护现场,从子程序返回后再恢复现场。通常在主程序中保护现场,则一定在主程序中恢复;在子程序中保护现场,则一定在子程序中恢复。这样可以增强主程序和子程序之间的相对独立性,减少相互依赖,使程序结构清楚,减少错误。汇编语言程序设计保护现场和恢复现场的方法(1)利用压栈和出栈指令,将寄存器内容或状态标志位内容保存在堆栈中,恢复时再从堆栈中取出。如:SUBTPROCNEARPUSHAX;保存现场PUSHBXPUSHCXPUSHDX...;子程序正常工作POPDX;恢复现场POPCXPOPBXPOPAXRETSUBTENDP汇编语言程序设计保护现场和恢复现场的方法在子程序设计时,应仔细考虑哪些寄存器是必须保存的,哪些寄存器是不必要保存的。一般来说,子程序中用到的寄存器是应该保存的。(2)利用内存单元。用传送指令将寄存器的内容保存到指定的内存单元,恢复时再用传送指令取出。汇编语言程序设计设计子程序时应考虑的问题(1)子程序名(子程序入口地址):用过程(子程序)定义伪指令定义该过程(子程序)时的过程名,这时过程(子程序)中第一条语句必须是子程序的入口指令;否则应写子程序入口指令的标号或地址。(2)子程序功能:用自然语言或数学语言等形式简单清楚地描述子程序完成的任务。(3)入口参数:说明子程序要求有几个入口参数,这些参数表示的意义及存放位置。(4)出口参数:说明子程序有几个输出参数(运行结果),这些参数表示的意义、存放的位置。(5)受影响的寄存器:说明子程序运行后,哪些寄存器的内容被破坏了,以便使用者在调用该子程序之前注意保护现场。汇编语言程序设计子程序的参数传递参数传递通常有三种方法:1、通过寄存器传递参数2、通过地址表传递参数地址3、通过堆栈传递参数或参数地址汇编语言程序设计通过寄存器传递参数通过寄存器进行主程序和子程序之间的参数传递是最常用的参数传递方式。由于CPU中的寄存器是有限的,因此通过寄存器传递参数适用于入口参数较少的情况。它一般通过寄存器传递数据或数据地址。常用:AL,AX,DX寄存器传数据,用SI,DI,BX传地址。汇编语言程序设计子程序的参数传递例编制程序计算:Z=√2X+√3Y+√150设X,Y为整数字数据,且存于PX和PY字单元,计算结果存入RLT字单元。汇编语言程序设计例子开平方子程序和调用程序,约定将被开平方数放在DX中,平方根也放在DX中,其结果求得平方根的整数部分。1:;*****LZ601S*****2:SQROOTPROCNEAR3:XORAX,AX;i←04:ANDDX,DX;测试被开方数5:JZSQRT2;被开方数为06:SQRT1:MOVBX,AX;形成奇数7:SHLBX,18:INCBX9:SUBDX,BX;被开方数减去奇数10:JCSQRT2;不够减11:INCAX;够减,i增112:JMPSQRT1;继续13:SQRT2:MOVDX,AX;DX←平方根14:RET;返回15:SQROOTENDP汇编语言程序设计例子2:SSEGSEGMENTSTACK3:STKTOPDB20DUP(0)4:SSEGENDS5:DSEGSEGMENT6:PXDW2007:PYDW3008:RLTDW09:DSEGENDS10:CSEGSEGMENT11:ASSUMECS:CSEG,DS:DSEG12:ASSUMESS:SSEG13:MAIN:MOVAX,DSEG14:MOVDS,AX15:MOVAX,SSEG16:MOVSS,AX汇编语言程序设计例子17:MOVSP,SIZESTKTOP18:MOVDX,PX;取X19:ADDDX,DX;计算2X20:CALLSQROOT1;21:PUSHDX;暂存结果√2X22:MOVDX,PY;取Y23:MOVAX,DX;计算3Y24:ADDDX,DX25:ADDDX,AX26:CALLSQROOT1;27:POPAX;取出√2X28:ADDAX,DX;计算√2X+√3Y29:PUSHAX;30:MOVDX,15031:CALLSQROOT132:POPAX;33:ADDAX,DX;34:MOVRLT,AX;35:MOVAH,4CH36:INT21H37:CSEGENDS38:ENDMAIN1SQROOT1PROCNEARXORAX,AXANDDX,DXJZSQRT2SQRT1:MOVBX,AXSHLBX,1INCBXSUBDX,BXJCSQRT2INCAXJMPSQRT1SQRT2:MOVDX,AXRETSQROOT1ENDP汇编语言程序设计例子17:MOVSP,SIZESTKTOP18:MOVDX,PX;取X19:ADDDX,DX;计算2X20:CALLSQROOT1;21:PUSHDX;暂存结果√2X22:MOVDX,PY;取Y23:MOVAX,DX;计算3Y24:ADDDX,DX25:ADDDX,AX26:CALLSQROOT1;27:POPAX;取出√2X28:ADDAX,DX;计算√2X+√3Y29:PUSHAX;30:MOVDX,15031:CALLSQROOT132:POPAX;33:ADDAX,DX;34:MOVRLT,AX;35:MOVAH,4CH36:INT21H37:CSEGENDS38:ENDMAIN1SQROOT1PROCNEARXORAX,AXANDDX,DXJZSQRT2SQRT1:MOVBX,AXSHLBX,1INCBXSUBDX,BXJCSQRT2INCAXJMPSQRT1SQRT2:MOVDX,AXRETSQROOT1ENDP①②③④⑤初始态(执行指令①后)0BH0DH0EH0FH10H11H
本文标题:第六章子程序设计.
链接地址:https://www.777doc.com/doc-2087988 .html