报错:relocation truncated to fit: R_ARM_THM_JUMP11 against symbol
环境:GNU GCC 平台:STM32F103C8T6
自己在写代码,写着写着就突然就报了个这个错误:
relocation truncated to fit: R_ARM_THM_JUMP11 against symbol “main”
搜了一下说是超出b指令的范围,但是我印象中的b指令是-32M~32M,但是我代码量也就5k,怎么跳都跳不出32M,然后我看了一下能正常编译过的反汇编代码,如下:
b指令的机器代码有16位,算一下16位达不到32M,其中还有指令码,剩下的实际数更达不到。我就猜测应该这里的原因,因为用到16位指令,跳转范围超了。
因为使用的是STM32F103C8T6,cortex-m3内核,armv7-m指令集,所以查看了下armv7-m的手册,查到了b指令的描述,
16位
b指令使用的是相对pc指令的偏移,计算方式为imm8左移1位,由于包含符号位,所以表示的范围为-2048~2046,看了下自己写的代码,这个范围很容易就超了。
再看下32位的b指令描述:
偏移由S+J1+J2+imm10+imm11组合而成,具体算法不细说,表示的范围为 -16777216~16777214。
原因找到了,回到自己写的代码,要使用32位b,可以增加点缀b.w,可是加上去编译又报错:
unexpected character `w’ in type specifier
对比了下开源工程,发现汇编开头少了一段描述:
.syntax unified
可加到如下处:
猜测加了这一段就才可以使用UAL(统一汇编语言)语法,.w也是属于UAL。好了,加上后再次编译,没有报错,看下反汇编:
使用的确实是32位的指令,而且发现加了.syntax unified不用显式的使用b.w,直接用b编译后就是用的32位。
总结:
-
代码跳转偏移超出b指令的范围,编译会报错,如遇到这样的错误可以排查下指令的范围。
-
GNU ARM编译下使用汇编后缀.w或.n需要增加描述.syntax unified才可。
最后有些问题还是需要自己跑一遍、还有查找各种资料才能得出结果,比如b指令的跳转范围在不同架构下都是不同的。