修复后无效的常量?

Kri*_*oks 24 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
Run Code Online (Sandbox Code Playgroud)

我不知道为什么会这样做.当我把一个较小的常数放入其中时r7,它工作正常.但随着数字越来越多,它会吐出这个错误.做我的临时固定它mov r7, #300add r7, #70,达到了预期的效果.仍不确定导致错误的原因.

Nic*_*rth 43

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
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 你是如何通过多步构造价值来解决它的.
  2. 通过使用ldr从内存加载值:ldr r7,=#370汇编器然后将创建一个常量池并通过pc相对寻址从那里加载值.

通常,您应该更喜欢使用最多2个指令构造常量,如果不可能(或者值必须是可重定位的)使用ldr.

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