[英]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/cl
( c
约束)中的寄存器操作数。 (特别是在cl
,因为我转向(uint8_t)
。
另外,我使用b
修饰符来覆盖大小,以防你想要在转换之前使用整个rcx
作为其他东西的命名输入。 (参见gcc文档中的6.45.2.8 x86操作数修饰符 )。
有关某些指南,另请参阅inline-assembly标记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.