我尝试了解如何在BL指令ARMv7a中计算目标地址。
我创建了一个简单的示例程序并编译并链接它。目标文件(elf)具有以下说明。
...
14: e3400000 movt r0, #0
18: eb00000f bl 5c <test>
1c: e50b0008 str r0, [fp, #-8]
...
0000005c <test>:
5c: e52db004 push {fp} ; (str fp, [sp, #-4]!)
60: e28db000 add fp, sp, #0
如果我理解BL正确,我应该得到5c作为目标地址。
从参考手册中我找到了以下描述:
imm32 = SignExtend(imm24:'00', 32);
targetAddress = PC + imm32;
其中imm24是指令的右24位。在我的情况下0x000000f。
如果我以这种方式计算目标地址,我就不会得到5c。
// PC = 0x18 (where we find the BL instruction)
uint32_t imm24 = 0x00000f;
uint32_t imm32 = imm24 << 2;
// imm32 = 0x3c
uint32_t targetAddress = PC + imm32;
// targetAddress = 0x18 + 0x3c = 0x54
我错过了什么吗?
我使用了带有以下标志的arm-none-eabi交叉编译器:
CFLAGS=-Wall -O0 -march=armv7-a -mtune=cortex-a7 -marm
答案 0 :(得分:2)
来自ARM ARM(文档编号DDI 0100E):
分支目标地址由以下公式计算:
将24位带符号(2的补码)立即符号扩展为32位。
将结果移位两位。
- 醇>
将此内容添加到PC的内容中,其中包含分支指令的地址加上8。
至于为什么会这样,请参阅同一文档中的 2.7.4预取和自修改代码。