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

Cortex-M4平台movw/movt替换为ldr后代码失效问题咨询

修改后代码失效的原因

ldr r0, =0x40023800属于汇编伪指令,实际会被汇编器转换为PC相对寻址的内存加载指令,32位立即数不会被编码到指令里,而是存放在代码段末尾的文字池(Literal Pool)中,执行时需要从内存读取该值到寄存器。而你原来用的movw/movt组合是直接将立即数的高低16位编码到指令中,执行时不需要访问内存。
故障大概率是以下两种场景导致的:

  • 链接地址与实际运行地址不匹配,且地址映射配置错误:你编译出的代码段基址为0x0,而STM32F4仅在BOOT引脚设为从主Flash启动时,0x0地址才会别名映射到Flash实际的基地址0x08000000。如果BOOT模式配置错误,0x0地址会映射到SRAM或者系统存储区,此时读取文字池得到的寄存器值不是预期的外设地址,后续访问外设自然失败。
  • 文字池内容未被正确加载:如果你是将代码放到RAM中运行,或者你的烧录/加载流程仅复制了可执行指令部分,没有把末尾的文字池数据一同复制到对应运行地址,读取到的立即数就是随机垃圾值,导致故障。

32位立即数写入寄存器的方案

ARMv7-M(Cortex-M4属于该架构)的指令集里,不存在可以直接编码任意32位立即数到寄存器的单条原生指令,因为单条32位指令的编码空间不足以同时存放操作码和完整的32位立即数。
你可以根据需求选择以下方案:

  • 如果你希望写汇编时只用单行代码,不需要手动拆分高低16位,可以使用GNU汇编器的mov32伪指令,它会自动被展开为movw/movt的组合,本质是两条指令,但不需要你手动计算立即数的高低位。
  • 如果你坚持用单条原生指令,只能继续使用ldr伪指令,但需要做对应适配:在代码中合适的位置插入.ltorg指令手动放置文字池,避免文字池和加载指令的偏移超出访问范围,同时确保链接地址和实际运行地址匹配,或者配置正确的地址映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:45:08