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>
失效原因分析
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输出逻辑。未指定section的
.space指令导致内存布局混乱
代码中.space 0x80200000-0x80000004未指定所属section,会被默认放入.text段,导致.text段从0x80000000开始占用0x1FFFFC(约2MB)的空间,虽然这不是导致失效的直接原因,但会破坏正常的内存布局,可能引发其他潜在问题。
内容的提问来源于stack exchange,提问作者odnal
相关产品推荐
相关产品推荐

