【发布时间】:2020-08-18 13:40:10
【问题描述】:
我想在位置 p 设置一个位,而不使用带有内联 asm gcc c 代码的 btsl 指令。使用 btsl 指令很简单:
int n,p;
scanf("%d%d",&n,&p);
asm("btsl %1, %0"
:"=m"(n)
:"Ir"(p)
:"cc");
我知道设置位是可以做到的:
n|=1<<p;
现在,我正在使用内联 asm:
asm("movl %1, %%eax;"
"movl %2, %%ebx;"
"shl $1, %%ebx;"
"orl %%ebx, %%eax;"
"movl %%eax, %0;"
:"=b"(n)
:"a"(n), "b"(p)
:"cc");
printf("%d\n",n);
在我看来 shl 指令不起作用。例如 n=20=10100。当我尝试设置第一位 p=1 时,结果是 22=10110 而不是 21=10101
【问题讨论】:
-
另外,
shl $1, %%ebx不会像您认为的那样做。它将ebx移动1而不是1移动ebx。 PS:不要在内联汇编中使用mov,只使用适当的约束。您已经为p指定了b作为输入,因此编译器已经将它放入ebx。所以movl %2, %%ebx只是扩展为毫无意义的movl %ebx, %ebx。n也一样。您也忘记将%eax指定为输出/clobber。 -
请注意,您将
eax指定为输入寄存器,然后继续覆盖它。这是不允许的。 -
如果您将其指定为输出(或一个clobber,但如果它已经是一个输入则不支持),您可以覆盖它。您的代码实际上应该只包含
shl和or并在输入和输出中使用约束。 -
为什么除了
shl之外的每条指令都使用冗余的l操作数大小后缀?无论如何,这并不重要,我认为使用内联汇编没有任何意义。只需使用较旧的 GCC 编译x|=1<<p;(错过 BTS 窥孔优化或选择不使用它),然后查看 asm 输出 (How to remove "noise" from GCC/clang assembly output?),如果您好奇什么 asm 序列将实现这一点。 -
btsl 有什么问题?如果你的 CPU 坏了,你应该更换 CPU。
标签: c assembly gcc x86 inline-assembly