为什么AS有时会接受超大排量,有时候不接受?

时间:2014-06-14 13:59:10

标签: assembly x86-64 gas

我知道MOD + R / M字段中的位移最大是一个带符号的32位整数。但是,当我传递一个对于32位有符号的值太大但对于无符号32位小的值时,我发现了一些不一致的行为。

案例:

.intel_syntax noprefix
mov [eax + eax + 0xdeadbeef], al
mov [r10d + r10d + 0xdeadbeef], al
mov [rax + rax + 0xdeadbeef], al
mov [r10 + r10 + 0xdeadbeef], al

当我收集(和dissasamble)时,我得到以下结果:

0:  67 88 84 00 ef be ad    mov    BYTE PTR [eax+eax*1-0x21524111],al
7:  de
8:  67 43 88 84 12 ef be    mov    BYTE PTR [r10d+r10d*1-0x21524111],al
f:  ad de
11: 88 04 00                mov    BYTE PTR [rax+rax*1],al
14: 43 88 04 12             mov    BYTE PTR [r10+r10*1],al

可以看出,对于32位寄存器(eaxr10d),32位位移按字面意思(并解释为带符号的32位整数)和64-位寄存器(raxr10),它被丢弃。

虽然我认为两者都是输入的合理输出,但我没有立即看到这种不一致处理的原因。这是在某处记录的吗?

1 个答案:

答案 0 :(得分:3)

似乎是intel语法模块中的一个错误。如果您使用& t语法:

,则会出现错误消息
mov %al, 0xdeadbeef(%rax, %rax)

结果:

Error: 0xdeadbeef out range of signed 32bit displacement

更新:该错误似乎是因为baseindex标志在i386_finalize_displacement被调用后设置,只有在设置时才会检测到错误。一个简单的解决方法是移动之前设置的标志。我没有看到任何明显的问题,至少解决了这个问题:

--- tc-i386-intel.c.orig        2012-01-16 04:06:06.000000000 +0100
+++ tc-i386-intel.c     2014-06-14 16:13:31.238740524 +0200
@@ -835,6 +835,9 @@
       memcpy (expP, &exp, sizeof(exp));
       resolve_expression (expP);

+      if (intel_state.base || intel_state.index)
+       i.types[this_operand].bitfield.baseindex = 1;
+
       if (expP->X_op != O_constant
          || expP->X_add_number
          || (!intel_state.base
@@ -882,9 +885,6 @@
            return 0;
        }

-      if (intel_state.base || intel_state.index)
-       i.types[this_operand].bitfield.baseindex = 1;
-
       if (intel_state.seg)
        {
          for (;;)