修复后无效的常量?

时间:2012-04-21 17:24:55

标签: assembly arm

出于某种原因,当我尝试编译这段代码时,编译器会说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, #300add r7, #70临时修复了它,达到了预期的效果。仍不确定导致错误的原因。

1 个答案:

答案 0 :(得分:41)

ARM指令只能使用mov加载有限范围的立即值。问题是该值必须在mov指令本身中编码。由于所有ARM指令都是32位宽,因此ARMv5的原始指令设置总共只有8 + 4位来编码。第一个8位能够在0-255的范围内加载任何8位值int,而右边的4位在0到30之间以2的步长旋转。

因此您可以加载以下值:

#0
#122
#121 ror #24 = 30976
#230 ror #12 = 241172480

但是,#370不能用这个方案加载,它需要像#185 ror #31这样的东西是不可能的。

有两种方法可以加载您的直接值。

  1. 你是如何通过多步构建值来解决它的。
  2. 通过ldr加载内存中的值:ldr r7,=#370然后汇编器将创建一个常量池,并通过pc相对寻址从那里加载值。
  3. 通常你应该更喜欢用最多2个指令构造常量,如果不可能(或者值必须是可重定位的)使用ldr。

    从ARMv7开始,您还可以使用movw在寄存器的下半部分加载任何16位值,同时将上半部分归零,movt将另一个16位值加载到上半部分而不用触摸下半部分。