且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-01-21 02:13:58

该内联程序集存在错误:

That inline assembly is buggy:

  1. 它使用有效连接的多行字符串.如果没有\n,则全部显示在一行上.是否用分号分隔的汇编程序 accepts 语句使所有区别都存在……有些可能不会.
  2. 它指定与输入/输出约束相同的变量,而不是通常针对这种情况使用"+r"(value).
  1. It uses multi-line strings which effectively concatenate. Without \n all appears on one line. Whether your assembler accepts statements separated by semicolons makes all the difference there ... some may not.
  2. It specifies the same variable as input/output constraint instead of using "+r"(value) as ordinarily suggested for this situation.

在没有看到其余代码的情况下,并不清楚为什么内联汇编语句看起来像它的样子.就个人而言,我建议这样写:

Without seeing the rest of the code it's not quite clear why the inline assembly statement looks the way it does; Personally, I'd suggest to write it like:

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

因为在组装时几乎不需要自己进行计算. uintptr_t(来自<stdint.h>)强制转换也使该32/64位不可知.

because there's little need to do the calculation itself in assembly. The uintptr_t (from <stdint.h>) cast makes this 32/64bit agnostic as well.

如果您希望将其用于不同的 CPU但x86/x64,则显然需要有所不同...对于ARM( not Thumb2),它会是:

If you want it for a different CPU but x86 / x64, then it obviously needs to be different ... For ARM (not Thumb2), it'd be:

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

因为那是旋转指令的行为方式.

since that's how the rotate instruction there behaves.

编辑(添加参考):

关于此处执行的操作,此博客文章给出了一个有趣的观点-即,编译器很可能会为以下内容创建相同的输出:

Regarding the operation performed here as such, this blog post gives an interesting perspective - namely, that the compiler is quite likely to create the same output for:

(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

Ergo,此内联程序是不必要的.

Ergo, this inline assembly is unnecessary.