单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,朱亚萍,zhuyp,杭州电子科技大学自动化学院,微机原理与接口技术,第四章 汇编语言程序设计,1,4-4,程序设计方法,子程序结构,1,子程序使用,子程序:,将多次使用的程序段写成一个相对独立的程序段,称为子程序或过程。,子程序结构的定义:,使用过程定义语句,PROCENDP,。,属性:,调用程序和过程在同一代码段中,则用,NEAR,属性,;,调用程序和过程不在同一代码段中,使用,FAR,属性,。,主过程,定义为,FAR,属性,看作,DOS,调用的一个子过程。,四、子程序结构,2,4-4,程序设计方法,子程序结构,子程序说明:,功能描述:名称,功能及性能,寄存器和存储单元,入口参数,出口参数,调用其它子程序的名称,3,4-4,程序设计方法,子程序结构,例,4-11,有一个子程序说明如下:,;名称:,BCD2BIN,;,功能:将一个字节的,BCD,码转换成二进制数,;所用寄存器:,CX,;,入口参数:,AL,存放两位,BCD,码,;出口参数:,AL,存放二进制数,;调其它子程序:无,若,AL=X,1,X,0,H,,则,转换方法为,:,X,1,10,X,0,子程序形式如下:,4,4-4,程序设计方法,子程序结构,BCD2BINPROC NEAR,(或,FAR,),PUSH CX,MOV CH,,,AL,AND CH,,,0FH,;,存,个位,MOV CL,,,4,SHR AL,,,CL,;高,4,位右移,4,位后乘,10,,即,十位乘,10,MOV CL,,,10,MUL CL,ADD AL,,,CH,;,高,4,位乘,10,后加低,4,位,POP CX,RET,BCD2BIN ENDP,5,4-4,程序设计方法,子程序结构,说明:,保护调用程序的断点,由,CALL,指令本身完成。要注意堆栈的使用,防止弹出地址值错误。,保护某些寄存器内容,在子程序开头,用一组,PUSH,指令,保护的寄存器原来的内容;,在子程序结尾,用一组,POP,指令,将寄存器原来的内容恢复。,注意,PUSH,和,POP,指令组的使用次序!,6,4-4,程序设计方法,子程序结构,主程序与子程序相互之间参数的传递,用寄存器传递参数,:参数较少,速度较快。,用存储器传递参数,:参数较多,需事先在存储器中建立一个参数表。,用堆栈传递参数,:参数较多,多用在子程序嵌套与递归调用中。,7,例,4-14,数据段定义两个数组,编程序实现数组段分别求和(,不计溢出,)。,本例,通过存储器来传递参数。,相应程序如下:,DATASEGMENT,ARY1DW,1234H,,,2233H,,,100 DUP(?),;定义数组,1,SUM1 DW?,ARY2DW 3456H,,,2783H,,,100 DUP(?),;定义数组,2,SUM2DW?,DATA ENDS,;,STACK SEGMENT STACK,SA,DB,100 DUP(?),TOP EQU LENGTH SA,STACK ENDS,4-4,程序设计方法,子程序结构,8,CODESEGMENT,ASSUME CS:CODE,,,DS:DATA,,,SS:STACK,MAINPROC FAR,START,:,MOVAX,,,DATA,MOV DS,,,AX,MOV AX,,,STACK,MOV SS,,,AX,MOV SP,,,TOP,LEA SI,,,ARY1,;数组,1,首地址,入口参数,MOV CX,,,SUM1,ARY1,;,数组,1,字节数,SHRCX,,,1,;除以,2,,数组,1,的字数,CALL SUM,;调用求和子程序,LEA SI,,,ARY2,;数组,2,首地址,入口参数,MOV CX,,,SUM2,ARY2,;数组,2,字节参数,SHRCX,,,1,;除以,2,,数组,2,的字数,4-4,程序设计方法,子程序结构,9,4-5,程序设计方法,子程序结构,CALL SUM,;调用求和子程序,MOV AH,,,4CH,;返回,DOS,INT 21H,RET,MAINENDP,SUMPROCNEAR,;子程序,XOR AX,,,AX,;,AX,清,0,L1,:,ADD AX,,,WORD PTRSI,;加数组元素,INC SI,INC SI,LOOP L1,MOV WORD PTRSI,,,AX,;数组和送入,SUM,RET,SUMENDP,;子程序返回,CODEEDNS,END START,10,例,4-15,通过堆栈传递参数,实现十进制数数组求和,要求主程序和过程不在同一个代码段中,要进行段间调用。相应程序如下:,MDATA SEGMENT,ARY1 DB ,20 DUP(?),;,定义数组,1,SUM1 DW?,N1EQUSUM1,ARY1,ARY2DB ,20 DUP(?),;,定义数组,2,SUM2 DW?,N2EQUSUM2,ARY2,MDATA ENDS,MSTACKSEGMENT STACK,SB DW 100 DUP(?),TOP LABEL WORD,MSTACK ENDS,4-4,程序设计方法,子程序结构,11,MCODE SEGMENT,;主程序段,ASSUME CS:MCODE,,,DS:MDATA,,,SS:MSTACK,MAIN PROC FAR,START:MOVAX,,,MSTACK,;初始化,SS,,,SP,MOV SS,,,AX,MOV SP,,,OFFSET TOP,PUSHDS,;程序段前缀,MOV AX,,,0,PUSH AX,MOV AX,,,MDATA,;初始化,DS,MOV DS,,,AX,4-4,程序设计方法,子程序结构,12,MOV AX,,,OFFSET ARY1,;,PADD,过程入口参数进栈,PUSH AX,MOV AX,,,N1,;,SIZE ARY1,PUSH AX,CALLFAR PTR PADD,MOV AX,,,OFFSET ARY2,PUSH AX,MOVAX,,,N2,;,SIZE ARY2,PUSHAX,CALLFAR PTR PADD,RET,MAINENDP,MCODE ENDS,4-4,程序设计方法,子程序结构,13,PCODESEGMENT,;,过程段,ASSUME CS,:,PCODE,,,DS,:,MDATA,,,SS,:,MSTACK,PADD PROCFAR,PUSH BX,;寄存器保护,PUSHCX,PUSHBP,MOVBP,,,SP,PUSHF,MOVCX,,,BP+10,;数组长度,CX,MOVBX,,,BP+12,;数组,ARY,起始地址,BX,MOVAX,,,0,NEXT,:,ADD AL,,,BX,;,数组相加,DAA,4-4,程序设计方法,子程序结构,14,MOV DL,,,AL,MOV AL,,,0,;调整进位,ADCAL,,,AH,DAA,MOVAH,,,AL,MOVAL,,,DL,INCBX,LOOP NEXT,MOV BX,,,AX,;,送数组和,SUM,POPF,POP BP,POP CX,POP BX,RET 4,;返回作废参数,PADD ENDP,PCODE ENDS,END START,4-4,程序设计方法,子程序结构,15,4-4,程序设计方法,子程序结构,该例,用堆栈传递参数,,堆栈中数据变化如图,4-11,所示。,总结:,调用前通过堆栈传递两个参数:数组的偏移地址值,数组长度。,进入过程时重新定义,CS,段:指向当前代码段,PCODE,。,过程返回时:用返回指令,RET 4,,,将通过堆栈传递的,4,个参数作废。,16,4-4,程序设计方法,子程序结构,17,4-4,程序设计方法,子程序结构,堆栈的变化:,初始化后,,SP,指向堆栈底,堆栈为空;,主程序调用过程前,二个参数(数组偏移地址及数组长度)已入栈;,执行,CALL,指令时,返回地址自动入栈;,过程中:,BX,,,CX,,,BP,,,标志寄存器入栈;继续执行过程段,PCODE,程序,利用,BP,,,在堆栈中位置,BP,12,处获取数组偏移地址,在堆栈中位置,BP,10,处获取数组长度。,过程运行到,RET 4,之前,由,POP,指令将,PSW,,,BP,,,CX,及,BX,相继弹出。,堆栈中还有,4,个字节的参数,SIZE1,和,ARY1,会影响下次过程调用参数的正确传递,用,RET 4,将此,4,个字节的参数弹出作废。,18,4-4,程序设计方法,子程序结构,2,子程序嵌套与递归调用,子程序嵌套,:,子程序本身又调用其它子程序。只要堆栈空间足够嵌套的层数不限。,图,4-12,给出了子程序嵌套示意图。,递归调用,:,子程序调用子程序本身。,19,4-4,程序设计方法,子程序结构,例,4-16,要求计算,N,!,(N,0),解:递归调用的应用:,N,!,N(N,1)(N,2)1,N,!,1,,,N,0,N,!,N(N,1),!,,N,0,求,N,!即为计算,N(N,1),!,而(,N,1,)!要调用,N,!子程序,只要将调用参数修改即可。可以通过堆栈将调用参数、寄存器内容等保护起来,每调用一次将(,N,1,)有关信息入栈,直到,N,0,为止,然后开始返回,返回时将,N,乘以(,N,1,)!,直到,N,为设置值为止。,20,4-4,程序设计方法,子程序结构,具体程序如下:,ADATASEGMENT,P1DB Input the number:(06),$,;提示输入信息,P2DB The result is:,,,$,CRDB 0DH,,,0AH,,,$,;回车换行,ADATAENDS,ASTACKSEGMENT STACK STACK,SA DW 100 DUP(?),TOP LABEL WORD,ASTACK ENDS,21,ACODE SEGMENT,ASSUME CS:ACODE,,,DS:ADATA,,,SS:ASTACK,MAINPROC FAR,START,:,MOV AX,,,ASTACK,;初始化,SS,,,SP,MOV SS,,,AX,MOV SP,,,OFFSET TOP,PUSH DS,;程序段前缀,MOV AX,,,0,PUSH AX,MOV AX,,,ADATA,;,初始化,DS,MOV DS,,,AX,4-4,程序设计方法,子程序结构,22,MOVAH,,,09H,LEADX,,,P1,INT21H,;显示,Input the number:(06),MOVAH,,,01H,INT21H,;输入数字到,AL,并显示,ANDAL,,,0FH,MOVBL,,,AL,LEADX,,,CR,MOVAH,,,09H,INT21H,;回车换行,MOV DX,,,0,;,DX,为,N,!的结果,MOVAH,,,0,;插入此条指令!,MOV AL,,,BL,4-4,程序设计方法,子程序结构,23,CALL FACT,;输入:,AL=N,;输出:,DX=N!,MOV AX,,,DX,CALLB2TOBCD,;输入:,AX=16,位二进制;,;输出:,AX=4,位压缩型,BCD,码,MOVBX,,,AX,MOVAH,,,09H,;显示,The result is:,LEADX,,,P2,INT21H,CALLDISP,;输入:,BX=4,位压缩型,BCD,码;输出:在屏幕上显示,RET,MAIN ENDP,4-4,程序设计方法,子程序结构,24,FACTPROC,;,N!,子程序,CMPAL,,,0,JNZ CHN,MOV DL,,,1,;,N=0,N!=1,RET,;第一次执行此指令返回到,POP,指令,CHN,:,PUSH AX,;,N,入栈,DEC AL,;,N,1,CALLFACT,;,递归调用,FACT,子程序,POP AX,;,N,弹出,MUL DL,;,N,逐层返回相乘,MOV DX,,,AX,;送结果到内存,RET,;后,N,1,次执行次指令返回,FACT ENDP,4-4,程序设计方法,子