GCC映射文件中ISR地址与向量表实际值不符问题咨询
先还原你的问题场景:
GCC映射文件中显示USART0_RX_IRQHandler的地址为0x00001328,对应条目如下:
.text.USART0_RX_IRQHandler 0x00001328 0xe4 ./Source/interrupts_new.o 0x00001328 USART0_RX_IRQHandler但实际加载到ISR向量表0x0000006C位置的值为0x00001329,向量表对应区域数据为:
0x00000060 000012ED 00001301 00001315 00001329 í...........)...
这个现象完全正常,本质是ARM架构中Thumb指令集的标准处理机制,和内存对齐无关,我来给你拆解清楚:
Thumb指令集的模式标记位:
对于ARM Cortex-M这类默认使用Thumb指令集的内核,异常向量表中存储的入口地址最低位是一个模式标识位:设为1表示接下来要执行Thumb指令,设为0则表示ARM指令。而函数的实际物理起始地址是这个向量表值减去1,也就是0x00001329 - 1 = 0x00001328,正好和GCC映射文件里的地址完全匹配。映射文件与向量表的职责差异:
GCC生成的映射文件记录的是函数的实际物理起始地址,这个地址需要严格对齐到2字节(Thumb指令的长度是2或4字节,要求2字节对齐),所以你看到的是0x00001328;而向量表的作用是告诉CPU“去哪里执行异常服务程序,以及用什么指令集执行”,因此会在实际地址基础上把最低位置1,来标记Thumb模式,最终呈现为0x00001329。验证这个通用规则:
你可以观察向量表里的其他条目,比如0x00000060位置的0x000012ED,减去1得到0x000012EC,去映射文件里查找对应的函数,会发现它的实际地址就是这个值——这是所有使用Thumb指令集的ARM内核的统一处理逻辑,不是个例。
总结一下:这个差异是ARM架构为区分指令集而设计的标准行为,完全符合预期,不需要担心任何问题。
内容的提问来源于stack exchange,提问作者Gregory Helton

