You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RISC-V汇编运行时异常:地址越界(0x00000004)问题排查求助

解决RISC-V汇编阶乘程序的地址越界异常

核心错误分析

地址越界(0x00000004)的直接原因是Factorial函数的栈帧操作顺序错误:

  • 递归返回后,你先读取a1,紧接着回收栈空间addi sp, sp, 8,之后再尝试读取返回地址ra——此时栈指针已指向栈帧上方的无效区域,访问4(sp)必然触发越界。
  • 阶乘返回值的寄存器传递逻辑混乱:returnFactorial把结果存在a0,但递归计算时用a1做乘法,最后main里又错误地把a1移到a0,和printf的参数要求不匹配。
  • printf调用存在参数错误:没有将格式字符串地址传入a0,且.include "printf.s"放在代码段中间会导致符号冲突或代码重复。

修正方案

1. 修复Factorial函数的栈操作逻辑

必须先恢复返回地址ra,再回收栈空间,同时统一用a0传递阶乘结果:

Factorial:
    beqz a0, returnFactorial
    addi sp, sp, -8
    sw ra, 4(sp)
    sw a0, 0(sp)
    addi a0, a0, -1
    jal ra, Factorial
    # 先恢复ra和原输入值,再计算乘积
    lw ra, 4(sp)
    lw t0, 0(sp)
    addi sp, sp, 8
    mul a0, a0, t0  # 用a0保存最终结果
    jr ra

returnFactorial:
    li a0, 1  # 0! = 1,结果存入a0
    jr ra

2. 修正printf的参数传递

RISC-V调用约定中,printf要求a0为格式字符串地址,a1为第一个格式化参数。调整main中的参数准备逻辑:

main:
    la a0, ask1
    li a7, 4
    ecall

    li a7, 5
    ecall

    jal ra, Factorial
    # 准备printf参数:a0=格式字符串,a1=阶乘结果
    la a0, msg
    mv a1, a0
    jal ra, printf

    # 正确退出程序
    li a7, 10
    ecall

3. 调整printf的引入方式

将.include "printf.s"放在文件最开头,确保函数被正确加载:

.include "printf.s"  # 放在文件头部

.data
ask1: .string "Please enter a number to compute its factorial value:   "
msg: .string "The result is: %d\n"

.text
.globl main
# ... 后续代码 ...

完整修正代码

.include "printf.s"

.data
ask1: .string "Please enter a number to compute its factorial value:   "
msg: .string "The result is: %d\n"

.text
.globl main

main:
    la a0, ask1
    li a7, 4
    ecall

    li a7, 5
    ecall

    jal ra, Factorial
    la a0, msg
    mv a1, a0
    jal ra, printf

    li a7, 10
    ecall

Factorial:
    beqz a0, returnFactorial
    addi sp, sp, -8
    sw ra, 4(sp)
    sw a0, 0(sp)
    addi a0, a0, -1
    jal ra, Factorial

    lw ra, 4(sp)
    lw t0, 0(sp)
    addi sp, sp, 8
    mul a0, a0, t0
    jr ra

returnFactorial:
    li a0, 1
    jr ra

额外注意事项

  • RISC-V要求栈指针保持16字节对齐,当前8字节栈帧在递归深度较大时可能触发对齐错误,建议改为addi sp, sp, -16并调整存储位置。
  • 若输入数字过大,阶乘结果会溢出32位寄存器,可改用64位寄存器(如用mulw或mul指令适配位数)。

内容的提问来源于stack exchange,提问作者Cocomelon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:37:41