繁体   English   中英

如何在Intel语法中将汇编中的立即值传递给shr?

[英]How can I pass an immediate value to shr in assembly in Intel syntax?

根据该引用该引用shr指令支持通过CL寄存器和立即值移位1 但是,我似乎无法立即获得工作价值; 当我有这个代码时:

#include <stdint.h>

int main() {
  uint64_t v = 15;
  asm ("shr %[v], $0x04\t\n"
       : [v] "+r" (v)
       :
       : "cc"
       );
  return v;
}

我收到此错误消息:

$ gcc -masm=intel foo.c
foo.c: Assembler messages:
foo.c:5: Error: operand size mismatch for `shr'

如何将立即值传递给shr (不将其加载到CL ,我关心它,因为我正在针对寄存器压力瓶颈进行优化)。

您正在使用具有Intel汇编语法的指南。 GNU程序集(GAS)使用AT&T语法,它具有操作数的逆序。 改变他们的顺序似乎做得很好:

uint64_t v = 0xffff;
asm ("shr $0x04, %[v]\n"
   : [v] "+r" (v)
   :
   : "cc"
   );
printf("%llx", v);        // 0xfff

(您也可以用shrq替换shr以显式使用64位操作数)

如果您仍然希望像使用-masm=intel一样使用Intel语法,则必须从立即值中删除美元符号:

asm ("shr %[v], 4\n"
     ...)

如果你使用-masm=intel ,它会激活.intel_syntax noprefix Immediates不再采用$前缀。 (但对于地址,您需要OFFSET symbol )。 无论如何,不​​要使用$

显然,如果你只是想要一个班次,你应该用C代替内联asm https://gcc.gnu.org/wiki/DontUseInlineAsm (您可以屏蔽移位计数以避免UB的移位计数太高,例如旋转: C ++中循环移位(旋转)操作的最佳实践


但是如果你想将它用作需要内联asm的东西的一部分,那么你可以这样做,以允许旋转计数为C中的变量(在cl )或常量(立即)。我使用了"cJ"允许0-63立即数操作数( J )的约束 ,或rcx/ecx/cx/clc约束)中的寄存器操作数。 (特别是在cl ,因为我转向(uint8_t)

另外,我使用b修饰符来覆盖大小,以防你想要在转换之前使用整个rcx作为其他东西的命名输入。 (参见gcc文档中的6.45.2.8 x86操作数修饰符 )。

有关某些指南,另请参阅标记wiki。

我使用https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Multiple-assembler-dialects-in-asm-templates来使用AT&T或Intel语法模式正确编译和汇编。

Godbolt编译器资源管理器中 ,您可以看到这与gcc一起使用,但是对于inline-asm,clang与-masm=intel无法正常工作。 它仍然替换为%rdi而不是rdi并且无法组装。

static inline uint64_t shr (uint64_t v, unsigned c)
{
    // %b[c] is cl even if %[c] is ecx or whatever.
    asm ("shr  {%b[c],%[v] | %[v],%b[c]}"
         : [v] "+r" (v) 
         : [c] "cJ" ((uint8_t)c));  // the cast gets this to use cl
    return v;
}

uint64_t shr_variable(uint64_t v, int c) {
    return shr(v, c);
}

    mov     rax, rdi
    mov     ecx, esi
    shr   rax,cl
    ret


uint64_t shr_const(uint64_t v) {
    return shr(v, 13);
}

    mov     rax, rdi
    shr   rax,13
    ret

将其与纯C进行比较,使用-march=haswell

// can use SHRX with BMI2 available.  And can optimize much better
uint64_t shr_variable_purec(uint64_t v, unsigned c) {
    //c &= 63;  // optional, compiles to zero instructions on x86 because shr and shrx already do this.
    return v >> c;
}

    shrx    rax, rdi, rsi
    ret

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM