AVR汇编递归斐波那契函数实现结果异常求助
排查AVR汇编实现递归斐波那契的异常问题
首先明确:斐波那契数列的递归逻辑是 f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2),n=10的正确结果是55,你遇到的0、20、60这类异常输出,大概率是栈管理、寄存器保存/恢复、递归终止条件或求和逻辑出了问题。结合你给出的代码片段,我整理几个关键排查和修复方向:
1. 寄存器的保存与恢复必须严谨
AVR汇编里递归调用时,非调用者保存的寄存器(比如你用到的r18、r24)必须先压栈,否则下一层递归会直接覆盖这些寄存器的值,导致上一层的计算结果完全丢失。
看你当前的代码片段,recur函数入口没有做寄存器保存操作,这是典型的错误点。修复示例:
recur: push r18 ; 先把当前用到的寄存器压栈保存 push r24 push r2 ; 假设r2是传入的n参数,也要保存 ; --- 你的递归逻辑代码开始 --- ; ... ; --- 你的递归逻辑代码结束 --- pop r2 ; 退出前按逆序弹出恢复寄存器 pop r24 pop r18 ret
2. 递归终止条件必须明确
如果recur函数没有正确处理n=0和n=1的终止情况,会导致递归逻辑混乱,要么无限递归,要么基数计算错误。你需要在函数开头就判断这两个条件:
recur: push r18 push r24 push r2 cpi r2, 0 ; 判断n是否为0 breq return0 cpi r2, 1 ; 判断n是否为1 breq return1 ; --- 处理n>=2的递归逻辑 --- ; ... return0: clr r18 ; f(0)=0 rjmp end_recur return1: ldi r18, 1 ; f(1)=1 end_recur: pop r2 pop r24 pop r18 ret
3. 递归求和的栈管理不能出错
计算f(n-1)+f(n-2)时,你需要先保存f(n-1)的结果,再去计算f(n-2),否则后者会覆盖前者的值。常见错误是没把f(n-1)压栈保存,直接用寄存器承接导致丢失。
完整的求和逻辑示例(假设r2是传入的n,r18是返回值):
recur: push r18 push r24 push r2 cpi r2, 0 breq return0 cpi r2, 1 breq return1 ; 计算f(n-1) dec r2 call recur mov r24, r18 ; 把f(n-1)暂存到r24 ; 计算f(n-2) dec r2 ; 此时r2已经是n-2 call recur add r18, r24 ; 求和:f(n-1)+f(n-2) rjmp end_recur return0: clr r18 rjmp end_recur return1: ldi r18, 1 end_recur: pop r2 pop r24 pop r18 ret
4. 额外检查:数据溢出与指令正确性
虽然f(10)=55远小于8位寄存器的最大值255,但如果你的加法指令用错(比如误用adc带进位加法却没处理进位),也可能导致结果异常。另外要确认参数传递的寄存器是否正确,比如你是不是把n存在了其他寄存器,却在代码里错误地操作了r2?
最后建议你用AVR调试工具单步执行,观察每一步的寄存器值和栈内容,重点看递归终止时的返回值,以及求和步骤中两个子结果是否正确相加。
内容的提问来源于stack exchange,提问作者Kai
相关产品推荐
相关产品推荐

