一、子程序的嵌套 一个子程序作为调用程序去调用另一个子程序的情况称为子程序的嵌套。 嵌套深度:嵌套的层数称为嵌套深度。不受限制。 嵌套子程序的设计:没有什么特殊要求,除子程序的调用和返回应正确使用CALL和RET指令外,要注意寄存器的保护和恢复。如用堆栈传送数据要避免因堆栈使用中的溢出问题而造成子程序不能正确返回的错误。有两种可能发生堆栈溢出的情况: 堆栈上溢:如堆栈已满,但还想再存入信息,这种情况称为堆栈上溢。 堆栈下溢:如堆栈已空,但还想再取出信息,这种情况称为堆栈下溢。 递归子程序:子程序自己调用自己的情况称为递归调用,这种子程序称为递归子程序 二、嵌套深度 图1表示了嵌套深度为2时的子程序嵌套情况。
例1 两个6字节数相加。 分析:将一个字节相加的程序段设计为子程序。主程序分3次调用该子程序,但每次调用的参数不同。 程序如下: DATA SEGMENT ADD1 DB FEH,86H,7CH,35H,68H,77H ADD2 DB 45H,BCH,7DH,6AH,87H,90H SUM DB 6DUP(0) COUNT DB 6 DATA ENDS STACK SEGMENT DB 100DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MADD: MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV SI,OFFSET ADD1 MOV DI,OFFSET ADD2 MOV BX,OFFSET SUM MOV CX,COUNT ;循环初值为6 CLC AGAIN:CALL SUBADD ;调用子程序 LOOP AGAIN ;循环调用6次 MOV AX,4C00H INT 21H ;子程序入口参数:SI,DI,BX 出口参数:SI,DI,BX SUBADD PROC ;完成一个字节相加 PUSH AX ;保护AX的值 MOV AL,[SI] ;SI是一个源操作数指针 ADC AL,[DI] ;DI是另一个源操作数指针 MOV [BX],AL ;BX是结果操作数指针 INC SI INC DI INC BX POP AX ;恢复AX的值 RET SUBADD ENDP CODE ENDS END MADD 例2 把内存中的字变量NUMBER的值,转换为4个ASCII码表示的十六进制数码串,串的起始地址为STRING。 分析:把内存中的字变量NUMBER的值,转换为4个ASCII码表示的十六进制数码串的工作设计成一个子程序,在这个子程序中再调用另一个子程序,由它完成从BCD码到ASCII码的转换。 程序如下: DATA SEGMENT NUMBER DW 25AFH STRING DB 4DUP(?),0DH,0AH,‘$’ DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BEGIN: MOV AX,DATA MOV DS,AX MOV ES,AX LEA BX,STRING PUSH BX ;将参数(结果地址指针)压入堆栈 PUSH NUMBER ;将源数据压入堆栈 CALL BINHEX ;调用子程序 LEA DI,STRING MOV AH,9 INT 21H BINHEX PROC PUSH BP MOV BP,SP PUSH AX PUSH DI PUSH CX PUSH DX PUSHF ;以上为保护现场 MOV AX,[BP+4] ;取出NUMBER MOV DI,[BP+6] ;取出STRING的偏移地址 ADD DI,LENGTH STRING-1 ;使DI指向转换数据 MOV DX,AX ;保护原始数据 MOV CX,4 AGAIN: AND AX,0FH ;取低4位 CALL HEXD ;调子程序 STD STOSB ;保护转换数据 PUSH CX ;保护CX的值 MOV CL,4 SHR DX,CL MOV AX,DX POP CX LOOP AGAIN POPF POP DX POP CX POP DI POP AX POP BP RET 4 BINHEX ENDP HEXD PROC ;将AL中的BCD码转换成ASCII码 CMP AL,0AH JL ADDZ ADD AL,’a’-‘0’-0AH ;小写字母转换成ASCII码,若为大写 ADDZ: ADD AL,‘0’ ;字母,则再加ADD AL,7 RET HEXD ENDP CODE ENDS EDN BEGIN 例6.3 数的阶乘 1 按照阶乘的定义 n!= n*(n-1)! 这是一个递归定义式,可采用子程序的的递归调用形式。程序如下: DATA SEGMENT NUM DB 5 FNUM DW ? DATA ENDS STACK SEGMENT DB 100DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK BEGIN: PUSH DS MOV AX,0 PUSH AX MOV CX,1 PUSH CX MOV AH,0 MOV AL,NUM CALL FACTOR MOV FNUM,AX POP CX MOV AX,4C00H INT 21H FACTOR PROC CMP AX,0 JNZ IIA MOV DL,1 RET IIA: PUSH AX DEC AL CALL FACT IIA1: POP CX MUL CL ;CALL MULT IIA2: MOV DX,AX RET FACTOR ENDP CODE ENDS END BEGIN |
电工学习网 ( )
GMT+8, 2021-12-6 20:45