错误:'asm'中不可能的寄存器约束

时间:2011-12-07 13:48:49

标签: assembly compiler-errors

我在编译程序包时遇到了问题,我不是 真的是一个很好的程序员,但我试着为自己修复它,它仍然无法编译。 这是原始代码。:

#ifdef __GNUC__
asm("and $3, %%ecx;"
"shl $3 ,%%ecx;"
"ror %%cl, %0"
: "=r" (value)
: "r" (value), "c" (address));
#else

错误是。:

GBAinline.h:139:错误:'asm'中的寄存器约束不可能 (ifdef行是138)

这就是我试图让它看起来的方式。:

#ifdef __GNUC__
asm ("and $3 %%ecx,shl $3 %%ecx,ror %%cl, %0" : "=r" (value): "r" (value), "c" (address));

#else

但是,它不会起作用。这是一个gba模拟器,才有人问,VBA,这是 GBAinline.h的一部分。这个汇编程序让我疯了。

编辑:上面的问题处理得很好,我只是没注意哪个 我正在使用的编译器。 但是现在我从头文件中得到了这个代码的错误,我把它放在了pastebin上, 保持这里的东西更整洁...(对不起,如果这是错误的,我可以稍后改变)

这是包含导致错误的行的标题: http://pastebin.com/k3D4cg0d

这是它引用的C文件: http://pastebin.com/Ymg1X5dg

这就是这样的错误。:

/var/tmp/cc3zA0lH.s: Assembler messages: /var/tmp/cc3zA0lH.s:69: Error: bad instruction `sw $3,0(r3)',

等等其余部分。

1 个答案:

答案 0 :(得分:1)

内联装配是错误的:

  1. 它使用有效连接的多行字符串。没有\n的所有内容都出现在一行中。无论你的汇编程序接受以分号分隔的语句,都会产生不同......有些可能没有。
  2. 它指定与输入/输出约束相同的变量,而不是像通常建议的那样使用"+r"(value)
  3. 在没有看到其余代码的情况下,为什么内联汇编语句看起来像它的方式并不十分清楚;就个人而言,我建议写它:

    asm("ror %%cl, %0" : "+r"(value) : "c"((((uintptr_t)address) & 3) << 3)));
    

    因为在装配中几乎不需要进行计算。 uintptr_t(来自<stdint.h>)演员也使这个32 / 64bit不可知。

    修改

    如果你想要一个不同的 CPU而不是x86 / x64,那么它显然需要不同......对于ARM(不是 Thumb2),它是'是:

    asm("ROR %0, %0, %1" : "+r"(value) : "r"((((uintptr_t)address) & 3) << 3)));
    

    因为那是旋转指令的行为。

    编辑(添加参考):

    关于这里执行的操作,this blog post提供了一个有趣的视角 - 即编译器很可能为以下内容创建相同的输出:

    (a >> shift | a << (8 * sizeof(a) - shift))
    

    至于x86内联

    asm("ror %%cl, %0" : "+r"(a) : "c"(shift))
    

    测试:

    #include <stdint.h>
    
    int main(int argc, char **argv)
    {
        unsigned int shift = (int)((((uintptr_t)argv) & 3) << 3);
        unsigned int a = argc;
    #ifdef USE_ASM
        /*
         * Mark the assembly version with a "nop" instruction in output
         */
        asm("nop\n\t"
            "ror        %%cl, %0" : "+r"(a) : "c"(shift));
        return a;
    #else
        return (a >> shift | a << (8 * sizeof(a) - shift));
    #endif
    }
    

    编译/反汇编:

    $ gcc -DUSE_ASM -O8 -c tf.c; objdump -d tf.o
    
    tf.o:     file format elf64-x86-64
    
    Disassembly of section .text:
    
    0000000000000000 :
       0:   83 e6 03                and    $0x3,%esi
       3:   8d 0c f5 00 00 00 00    lea    0x0(,%rsi,8),%ecx
       a:   90                      nop
       b:   d3 cf                   ror    %cl,%edi
       d:   89 f8                   mov    %edi,%eax
       f:   c3                      retq
    $ gcc -O8 -c tf.c; objdump -d tf.o
    
    tf.o:     file format elf64-x86-64
    
    Disassembly of section .text:
    
    0000000000000000 :
       0:   83 e6 03                and    $0x3,%esi
       3:   8d 0c f5 00 00 00 00    lea    0x0(,%rsi,8),%ecx
       a:   d3 cf                   ror    %cl,%edi
       c:   89 f8                   mov    %edi,%eax
       e:   c3                      retq

    因此,这种内联汇编是不必要的。