问题描述
出于某种原因,当我尝试编译这段代码时,编译器说syscall.s:72:invalid constant (0x172) after fixup
:
For some reason, when I try to compile this bit of code, the compiler says syscall.s:72:invalid constant (0x172) after fixup
:
.globl _mach_msg_trap$MACH
_mach_msg_trap$MACH:
stmfd sp!, {r4,r7}
mov r7, #370 /* this is line 72 */
svc 0
ldmfd sp!, {r4, r7}
bx lr
我不知道它为什么这样做.当我将一个较小的常量放入 r7
时,它工作正常.但是对于更高的数字,它会抛出这个错误.我通过mov r7,#300
和add r7,#70
临时修复,达到了预期的效果.仍然不确定是什么导致了错误.
I don't know why it's doing it. When I put a smaller constant into r7
, it works fine. But with higher numbers, it spits out this error. I've temporary fixed it by doing mov r7, #300
and add r7, #70
, which achieves the desired effect. Still not sure what caused the error though.
推荐答案
ARM 指令集,直到 ARMv5,只能使用有限范围的立即数.问题是该值必须在指令本身中进行编码.由于所有 ARM 指令都是 32 位宽,因此直到 ARMv5 的原始指令集总共只有 8+4 位来编码立即数.第一个 8 位能够加载 0-255 范围内的任何 8 位值,而第 4 位是在 0 和 30 之间以 2 为步长进行右循环.
The ARM Instruction Set, up to ARMv5, is only able to use a limited range of immediate values. The problem is that the value has to be encoded in the instruction itself. As all ARM Instructions are 32-bit wide, the original instruction-set up to ARMv5 only had a total of 8+4 bits to encode immediates. With the first 8-bit being able to load any 8-bit value in the range of 0-255 and the 4 bit being a right rotate in steps of 2 between 0 and 30.
因此您可以加载如下值:
So you can load values like:
#0
#122
#121 ror #24 = 30976
#230 ror #12 = 241172480
但是,#370 不能用这个方案加载,它需要像 #185 ror #31
这样的东西,这是不可能的.
But, #370 is not loadable with this scheme, it would require something like #185 ror #31
which is not possible.
有两种方法可以加载您的即时价值.
- 您是如何通过分多个步骤构建值来解决它的.
- 通过使用 ldr 从内存中加载值:
ldr r7,=#370
然后汇编器将创建一个常量池并通过 pc- 从那里加载值相对寻址.
通常你应该更喜欢用最多 2 条指令来构造常量,如果那不可能(或者值必须可重定位),请使用 ldr.
Usually you should prefer to construct constants with up to 2 instructions, if thats not possible (or the value has to be relocatable) use ldr.
从 ARMv7 开始,您还可以使用 movw
在寄存器的下半部分加载任何 16 位值,同时对上半部分和 movt
在不触及下半部分的情况下将另一个 16 位值加载到上半部分.
Starting with ARMv7 you can also use movw
to load any 16 bit value in the lower half of a register while zeroing the top-half and movt
to load another 16bit value to the upper half without touching the lower half.
这篇关于修复后常量无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!