RISC-V实现阿克曼函数陷入死循环,无法输出正确结果求助
问题排查与修复
你的RISC-V汇编代码陷入无限循环的核心原因是参数初始化错误,同时存在一处冗余代码,以下是具体分析和修复方案:
1. 致命错误:main函数参数初始化逻辑错误
你在main函数中用以下代码传递阿克曼函数的参数:
addi a3, a3, 3 addi a4, a4, 4
RISC-V程序启动时,通用寄存器(如a3、a4)的初始值是未定义的,直接基于未知值做加法会导致传入ackermann的参数完全错误(比如n或m变成极大值),进而引发无限递归。
修复方式:从zero寄存器(固定值为0)初始化参数,确保传入的n=3、m=4是确定的:
addi a3, zero, 3 ; 初始化n为3 addi a4, zero, 4 ; 初始化m为4
2. 冗余代码(不影响功能但可优化)
在n_notzero分支中,调用ackermann后执行jal ra, return属于冗余操作:
jal ra, ackermann jal ra, return #return ackermann(n-1, 1)
当ackermann递归调用返回后,当前函数的栈帧还未恢复,直接跳转到return是正确的,但可以简化为让流程自然进入return(该冗余代码不会导致错误,仅影响代码简洁性)。
修复后的完整汇编代码
.globl main .text main: addi a3, zero, 3 ; 正确初始化n=3 addi a4, zero, 4 ; 正确初始化m=4 jal ra, ackermann addi a1, a0, 0 addi a0, zero, 1 ecall addi a0, zero, 10 ecall ackermann: addi sp, sp, -16 sw a4, 8(sp) sw a3, 4(sp) sw ra, 0(sp) bne a3, zero, n_notzero #n!=0 opposite of n==0 query addi a0, a4, 1 #m+1 jal ra, return#return m+1 n_notzero: bne a4, zero, m_notzero #m!=0 addi a3, a3, -1 addi a4, zero, 1 jal ra, ackermann jal ra, return #return ackermann(n-1, 1) m_notzero: #return ackermann(n-1, ackermann(n,m-1)) #ackermann(n,m-1) addi a4, a4, -1 jal ra, ackermann add t0, a0, zero #保存ackermann(n,m-1)的结果 add a4, t0, zero lw a3, 4(sp) addi a3, a3, -1 #n-1 jal ra, ackermann #调用ackermann(n-1, 结果) jal ra, return return: lw ra, 0(sp) addi sp, sp, 16 jalr zero, ra, 0
修复后运行代码,即可得到正确输出125。
内容的提问来源于stack exchange,提问作者Teslaq234
相关产品推荐
相关产品推荐

