.global _start
_start:
ldr r0,=label
adr r0,label
stop:
b stop
label:
.word 0x12345678
在学习adr指令时,对ldr与adr有些难以理解
debug后的对应的代码为
0x00000000 E59F0008 LDR R0,[PC,#0x0008] @//对应ldr
0x00000004 E28F0000 ADD R0,PC,#0x00000000 @//对应adr
乍一看,两条代码都与PC相关,我想不通为什么会因为运行地址不同而导致ldr取不到正确的标签地址。
0x00000010 0000000C ANDEQ R0,R0,R12
再仔细看,ldr是取得[PC,#0x0008]处存储的内容,而非是获得标签处的地址
举例说明,
@//写代码时
0x00000000 E59F0008 LDR R0,[PC,#0x0008] @//PC为0x00000008
0x00000004
0x00000008
0x0000000c 12345678 EORNES R5,R4,#0x07800000
0x00000010 0000000C ANDEQ R0,R0,R12 @//存储标签所在地址
0x00000014
@//运行时,假设运行地址从3000开始
0x00003000 E59F0008 LDR R0,[PC,#0x0008] @//PC为0x00003008
0x00003004
0x00003008
0x0000300c 12345678 EORNES R5,R4,#0x07800000
0x00003010 0000000C ANDEQ R0,R0,R12 @//此处存储的是编译前标签所在地址,
0x00003014 @//编译后内容不会更改,
@//所以ldr仍取到0000000C,
@//而此时正确的地址为0x0000300c
所以,ldr与adr都与PC相关,但adr是通过与标签的相对地址直接获取标签的地址。
ldr是通过与某一 存储标签地址的地址 的相对地址间接获取到编译前存在此处的标签地址,相当于”刻舟求剑“