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

RISC-V QEMU Virt平台栈指针初始化异常问题问询

RISC-V QEMU Virt栈指针初始化失效原因分析

背景

基于QEMU RISC-V Virt平台编写UART输出'U'的代码,测试栈指针初始化方案。已知Virt平台入口地址为0x80000000,128MB RAM(0x80000000~0x88000000)范围内可自由设置栈地址。

正常工作的三种实现

方案1:BSS段分配固定大小栈

.section .bss
.align 16
stack_bottom:
.skip 16384  # 16 KiB
stack_top:

.section .text
globl _entry
_entry:

    la sp, stack_top 

    # 为每个hart分配栈空间(当前使用4个hart)
    li a0, 1024*4
    csrr a1, mhartid
    addi a1, a1, 1
    mul a0, a0, a1
    add sp, sp, a0

    call start

方案2:BSS段分配到指定栈顶地址

.section .bss
.align 16
stack_bottom:
.space 0x80200000-0x80000004
stack_top:

.section .text
globl _entry
_entry:

    la sp, stack_top 

    # 为每个hart分配栈空间(当前使用4个hart)
    li a0, 1024*4
    csrr a1, mhartid
    addi a1, a1, 1
    mul a0, a0, a1
    add sp, sp, a0

    call start

方案3:基于AUIPC初始化栈指针

.section .text
globl _entry
_entry:

    auipc sp, 0x0

    # 为每个hart分配栈空间(当前使用4个hart)
    li a0, 1024*4
    csrr a1, mhartid
    addi a1, a1, 1
    mul a0, a0, a1
    add sp, sp, a0

    call start

失效的实现

编译正常但无法输出'U'的代码:

.space 0x80200000-0x80000004

.section .text
globl _entry
_entry:

    lui sp, 0x80200
    addi sp, sp, 0x000

    # 为每个hart分配栈空间(当前使用4个hart)
    li a0, 1024*4
    csrr a1, mhartid
    addi a1, a1, 1
    mul a0, a0, a1
    add sp, sp, a0

    call start

反汇编对比

失效实现反汇编

0000000080000000 <_entry>:
    80000000:   08020137                lui     sp,0x8020
    80000004:   00010113                mv      sp,sp
    80000008:   00001537                lui     a0,0x1
    8000000c:   f14025f3                csrr    a1,mhartid
    80000010:   00158593                addi    a1,a1,1
    80000014:   02b50533                mul     a0,a0,a1
    80000018:   00a10133                add     sp,sp,a0
    8000001c:   032000ef                jal     8000004e <start>

正常方案2反汇编

0000000080000000 <_entry>:
    80000000:   00210117                auipc   sp,0x210
    80000004:   ffc10113                addi    sp,sp,-4 # 8020fffc <stack_top>
    80000008:   00001537                lui     a0,0x1
    8000000c:   f14025f3                csrr    a1,mhartid
    80000010:   00158593                addi    a1,a1,1
    80000014:   02b50533                mul     a0,a0,a1
    80000018:   00a10133                add     sp,sp,a0
    8000001c:   032000ef                jal     8000004e <start>

失效原因分析

  1. LUI指令立即数超出范围,导致栈指针指向非法地址
    RISC-V的lui指令仅支持20位立即数,而代码中lui sp, 0x80200的立即数0x80200是21位(二进制共21位),汇编器会自动截断为低20位,最终生成的指令是lui sp, 0x8020(反汇编可见)。该指令将栈指针设置为0x8020 << 12 = 0x08020000,远低于Virt平台RAM起始地址0x80000000,属于非法内存区域。

    后续执行jal start时,需要将返回地址ra压入栈中,访问非法内存会触发硬件异常,程序直接终止,无法执行到UART输出逻辑。

  2. 未指定section的.space指令导致内存布局混乱
    代码中.space 0x80200000-0x80000004未指定所属section,会被默认放入.text段,导致.text段从0x80000000开始占用0x1FFFFC(约2MB)的空间,虽然这不是导致失效的直接原因,但会破坏正常的内存布局,可能引发其他潜在问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:19:50