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

QEMU中裸机ARM的str指令无执行效果问题排查

问题描述

我正在构建无操作系统、无引导加载程序的裸机应用,在QEMU中运行时发现str指令完全没有执行效果的异常。

我希望直接将程序注入RAM运行,参考修改了裸机链接脚本和启动文件startup.S来规划内存布局、搭建C环境,使用的是vexpress-a9平台(搭载cortex-a9处理器)。

我修改了启动文件,让程序直接从0x0地址的起始异常向量处执行(将其视为ROM),计划将.text段放在此处,完成.data、.bss和栈的初始化后跳转到main。

内存布局的链接脚本片段:

MEMORY
{
    ROM (rx) : ORIGIN = 0x00000000, LENGTH = 1M
    RAM (rwx): ORIGIN = 0x00400000, LENGTH = 4M
}

当前能正常启动QEMU、连接GDB并单步调试初始化代码,但本该在起始地址为0x00400000的"RAM"中完成的初始化完全没有生效。

以下汇编代码的目的是用0xFEFEFEFE填充FIQ栈段:将r1设为栈起始地址,sp设为栈结束地址,当r1 < sp时,将r0的值存入r1指向的地址,然后r1自增4字节。

Reset_Handler:
    /* FIQ stack */
    msr cpsr_c, MODE_FIQ
    ldr r1, =_fiq_stack_start
    ldr sp, =_fiq_stack_end
    movw r0, #0xFEFE
    movt r0, #0xFEFE

fiq_loop:
    cmp r1, sp
    strlt r0, [r1], #4   <<<< 问题所在
    blt fiq_loop

循环能按栈大小正确执行迭代次数,但strlt r0, [r1], #4指令完全没有效果。

执行str指令前,r1为栈起始地址,对应内存值为0x0:

>>> p/x $r1                                                                                                                   
$2 = 0x400008                                                                                                                
>>> x/2hx $r1                                                                                                                
0x400008:       0x0000  0x0000     

执行str指令后,r1已自增4字节,但栈起始地址的内存值仍为0x0:

>>> p/x $r1                                                                                                                   
$3 = 0x40000c 
>>> x/2hx 0x400008                                                                                                            
0x400008:       0x0000  0x0000 

内存未被更新,但我可以直接通过GDB修改该地址的值,说明内存本身可写:

>>> set *(0x400008)=0x12345678                                                                                                
>>> x/2hx 0x400008                                                                                                            
0x400008:       0x5678  0x1234 

我启动QEMU的命令为:

qemu-system-arm \
    -nographic \
    -s \
    -S \
    --no-reboot \
    -machine vexpress-a9 \
    -cpu cortex-a9 \
    -m 12M \
    -device loader,file=out.elf

编译时使用了-mcpu=cortex-a9选项,且已为QEMU分配足够内存,完全不清楚问题原因,恳请帮助。

进一步调试信息

根据要求,补充以下实体的状态信息:

  • _fiq_stack_start的值?

    0x00400008 —— 符合预期,FIQ栈应在8字节的.data段之后开始

  • _fiq_stack_end的值?

    0x00401008 —— 符合预期,我设置栈大小为4096字节

  • cmp指令执行时r1的内容?

    r1 = 0x00400008 —— 符合预期,r1应存储栈起始地址

  • sp寄存器的内容?

    0x00401008 —— 符合预期,这是栈的结束地址

  • strlt执行时的条件码位?

    比较前CPSR = 0x40000111,比较后CPSR = 0x80000111。这符合预期,因为r1的值小于sp,有符号正数比较结果会将第31位置1。

  • r0的内容?

    0xfefefefe —— 符合预期,通过两条mov指令将r0设为预期的栈填充值

  • 将strlt改为str会发生什么?

    我已测试过,结果完全相同。

我还尝试了以下简单指令:

mov r0, #0x1234
mov r3, #0x2
str r0, [r3] /* 将R0的值存入r3指向的地址 */

执行后预期r0的值0x1234会存入r3指向的0x2地址,但实际并未生效:

>>> p/x $r0
$7 = 0x1234

>>> p/x $r3
$8 = 0x2

>>> x/2hx $r3
0x2 <_Reset+2>: 0xea00  0x0041

看起来str指令被完全忽略了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:39:53