STM32F103ZET6 Bootloader跳转异常及Thumb模式指令疑问
STM32F103 Bootloader跳转与Thumb模式指令问题
场景说明
我使用Keil5开发STM32F103ZET6的Bootloader,Bootloader存放于Flash基地址0x08000000,完成操作后需跳转到应用地址0x08004000。
Bootloader跳转代码
#define apdr 0x08004001 void (*app)(void); app = ((void (*)(void))apdr); app();
应用反汇编代码
RESET __Vectors 0x08004000: 20002400 .$. DCD 536880128 0x08004004: 08004145 EA.. DCD 134234437 0x08004008: 08004151 QA.. DCD 134234449 Reset_Handler 0x08004144: f8dfd01c .... LDR sp,[pc,#28] ; [0x8004164] = 0x20002400 0x08004148: 4807 .H LDR r0,[pc,#28] ; [0x8004168] = 0x8004195 0x0800414a: 4780 .G BLX r0 0x0800414c: 4807 .H LDR r0,[pc,#28] ; [0x800416c] = 0x8004131 0x0800414e: 4700 .G BX r0
问题1:任意奇数地址跳转仍能运行的原因
- Cortex-M3指令特性:BX/BLX跳转指令会自动忽略目标地址的最低位,仅用高31位作为实际跳转地址,最低位用来指定指令模式——1对应Thumb模式,0对应ARM模式。STM32F103是Cortex-M3内核,仅支持Thumb模式,所以最低位必须为1。
- 向量表的自动执行:当跳转到
0x08004001这类奇数地址时,BX指令会截断地址为0x08004000(应用向量表起始地址),CPU会自动执行向量表流程:先加载栈顶指针(0x08004000处的值),再跳转到复位向量(0x08004004处的0x08004145,最低位1对应Thumb模式)。 - 中间地址的兼容性:对于
0x0800414D这类复位handler范围内的奇数地址,BX指令会截断为0x0800414C,该地址是复位handler中的合法指令,CPU执行后会继续后续初始化流程,因此应用仍能正常运行。
问题2:Thumb模式下32位LDR指令的有效性
完全可以正常工作,原因如下:
- Cortex-M3内核支持Thumb-2指令集,该指令集包含16位和32位混合指令,
ldr sp, =__initial_sp属于Thumb-2伪指令,编译器会将其转换为合法的32位Thumb指令(比如你反汇编中看到的f8dfd01c,就是32位的LDR sp,[pc,#28]指令)。 - 复位handler本身运行在Thumb模式下,Cortex-M3会自动识别并执行32位Thumb-2指令,无需额外配置,因此这条加载栈顶的指令可以正常完成初始化操作。
内容的提问来源于stack exchange,提问作者ugger B
相关产品推荐
相关产品推荐

