在使用Keil(版本为uVision V5.38.0.0)编译工程的时候碰到了一个报错:
Error: L6286E: Relocation #REL:0 in cm0dasm.o(.text) with respect to __main. Value(0xfffffffa) out of range (0 - 0xff) for (R_ARM_THM_PC8)
启动汇编代码如下所示
Reset_Handler PROC
GLOBAL Reset_Handler
ENTRY
IMPORT __main
LDR R0,__main
BX R0
ENDP
在网上搜了一些解答,像是CSDN有人说将编译优化等价修改为-O1,这肯定是在胡说八道。实际上ARM社区已经对此问题作出了解答。
此问题产生的原因是汇编指令尝试访问超出指令范围的符号,至于修改的方式,其实比较简单,只需要将第五行做如下改动
LDR R0,=__main
之前调试的时候我就发现,这里写的汇编代码的LDR其实不是汇编指令,而是伪代码。它的使用方式有两种
LDR {{<cond>}} {.W} {<Rt>}, ={<expr>}
LDR {{<cond>}} {.W} {<Rt>}, ={<label_expr>}
其中<expr>
是数值表达式,<label_expr>
是PC
或者外部地址加减一个数值。这一点从汇编器的结果就可以发现,例如上面程序汇编的结果为
0x00000094 4800 LDR r0,[pc,#0] ; @0x00000098
所以说一开始的写法其实是错误的,要跳转到符号地址应该用LDR
伪指令说明里提供的方法。
除此之外补充一点,因为LDR
其实是伪指令,所以汇编出的结果不一定是LDR
指令,也可能是MOV
指令。