一、子程序的嵌套
一个子程序作为调用程序去调用另一个子程序的情况称为子程序的嵌套。
嵌套深度:嵌套的层数称为嵌套深度。不受限制。
嵌套子程序的设计:没有什么特殊要求,除子程序的调用和返回应正确使用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
全站搜索