📄 dg.asm
字号:
;求解阶乘问题的递归算法。
STACK EQU 1FH ;用户堆栈所在页面。
BOTTOM EQU 00H ;用户堆栈栈底单元。
M EQU 200 ;用户堆栈的字节数。
TOP DATA 3EH ;用户堆栈栈顶指针。
N DATA 30H ;参数N存放单元(N=01H~0AH)。
NFACT EQU 31H ;N阶乘计算结果(BCD码)存放单元的首址。
ORG 0000H
LJMP TEST
ORG 100H
TEST: MOV SP,#5FH ;设置较大的系统堆栈。
LCALL SETNULL ;初始化用户堆栈。
MOV N,#5 ;计数5!
LCALL FACT0 ;结果得120
MOV N,#8 ;计数8!
LCALL FACT0 ;结果得40320
MOV N,#10 ;计数10!
LCALL FACT0 ;结果得3628800
STOP: LJMP STOP
FACT0: MOV A,N ;取参数N的值。
LCALL DPUSH ;压入用户堆栈。
LCALL FACT ;调用计算阶乘的子程序。
LCALL DPOP ;从用户堆栈取出三字节(十六进制)结果。
MOV R5,A ;高字节。
LCALL DPOP
MOV R6,A ;中字节。
LCALL DPOP
MOV R7,A ;低字节。
LCALL HBCD ;将其转换成BCD码(该子程序省略)。
MOV R0,#NFACT;然后将计算结果存放到指定单元。
MOV A,R1 ;转换后四字节BCD码在R1R2R3R4中。
MOV @R0,A ;传送到指定存放单元。
INC R0
MOV A,R2
MOV @R0,A
INC R0
MOV A,R3
MOV @R0,A
INC R0
MOV A,R4
MOV @R0,A
RET
FACT: LCALL DPOP ;计算阶乘的子程序入口,从用户堆栈取出阶数。
CJNE A,#1,FACT1;阶数为1否?
LCALL DPUSH ;阶数为1,将结果000001H压入用户堆栈。
CLR A
LCALL DPUSH
LCALL DPUSH
RET ;子程序返回。
FACT1: LCALL DPUSH ;阶数不是1,将当前参数保存到用户堆栈中。
DEC A ;将阶数降低一阶。
LCALL DPUSH ;压入用户堆栈。
LCALL FACT ;用新的阶数递归调用计算阶乘的子程序。
LCALL DPOP ;从用户堆栈中取出三字节十六进制计算结果。
MOV R5,A ;高字节。
LCALL DPOP
MOV R6,A
LCALL DPOP
MOV R7,A
LCALL DPOP ;从用户堆栈中取出保存的当前阶数。
MOV R3,A ;将其暂存在R3中。
MOV A,R7 ;计算R3×R5R6R7→R5R6R7。
MOV B,R3
MUL AB
MOV R7,A
MOV A,B
XCH A,R6
MOV B,R3
MUL AB
ADD A,R6
MOV R6,A
CLR A
ADDC A,B
XCH A,R5
MOV B,R3
MUL AB
ADD A,R5
MOV R5,A
MOV A,R7 ;将三字节计算结果压入用户堆栈。
LCALL DPUSH
MOV A,R6
LCALL DPUSH
MOV A,R5
LCALL DPUSH
RET ;子程序返回。
HBCD: CLR A ;将十六进制数R5R6R7转换成BCD码R1R2R3R4
MOV R1,A
MOV R2,A
MOV R3,A
MOV R4,A
MOV R0,#18H
HB3: MOV A,R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
DA A
MOV R3,A
MOV A,R2
ADDC A,R2
DA A
MOV R2,A
MOV A,R1
ADDC A,R1
DA A
MOV R1,A
DJNZ R0,HB3
RET
SETNULL:MOV A,#BOTTOM ;初始化空栈,取栈底单元位置。
MOV TOP,A ;使栈顶指针指向栈底。
RET ;设置好空栈。
DPUSH: MOV B,A ;保护待入栈数据。
MOV A,TOP ;先取栈顶指针的当前值。
INC A ;后移一个单元。
CJNE A,#M,PUSH1 ;满栈否?
SETB C ;满栈,入栈失败。
SJMP PUSHE ;结束。
PUSH1: MOV TOP,A ;新栈顶有效。
MOV DPH,#STACK ;取堆栈所在页面。
MOV DPL,TOP ;取栈顶单元位置。
MOV A,B ;取待入栈数据。
MOVX @DPTR,A ;压入栈顶。
CLR C ;入栈成功。
PUSHE: RET ;结束。
DPOP: MOV A,TOP ;数据出栈,先取栈顶指针的当前值。
CJNE A,#BOTTOM,POP1 ;空栈否?
SETB C ;空栈,出栈失败。
SJMP POPE ;结束。
POP1: MOV DPH,#STACK ;取堆栈所在页面。
MOV DPL,TOP ;取栈顶单元。
MOVX A,@DPTR ;取出栈顶元素。
DEC TOP ;指向新的栈顶。
CLR C ;出栈成功。
POPE: RET ;结束。
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -