⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dg.asm

📁 单片机程序设计基础 随书光盘
💻 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 + -