C++ 如何在内联汇编中实现这一点?

C++ 如何在内联汇编中实现这一点?,c++,assembly,x86-64,inline-assembly,C++,Assembly,X86 64,Inline Assembly,我在理解GNU内联汇编语法方面非常糟糕,所以我希望一个实际的例子能有所帮助。给定以下程序集(x86-64,通过叮当输出),我如何使用相同的内联程序集构造函数?GCC为同一个函数生成不同的代码,我想让它生成与Clang(-O3)输出相同的版本 bitest(无符号字符,int): btl%esi,%edi 挫折%al ret 以下是GCC(-O3)产生的结果: bitest(无符号字符,int): movzx-eax,dil mov ecx,esi sar-eax,cl 和eax,1 ret

我在理解GNU内联汇编语法方面非常糟糕,所以我希望一个实际的例子能有所帮助。给定以下程序集(x86-64,通过叮当输出),我如何使用相同的内联程序集构造函数?GCC为同一个函数生成不同的代码,我想让它生成与Clang(-O3)输出相同的版本

bitest(无符号字符,int):
btl%esi,%edi
挫折%al
ret
以下是GCC(-O3)产生的结果:

bitest(无符号字符,int):
movzx-eax,dil
mov ecx,esi
sar-eax,cl
和eax,1
ret
以下是该函数的C代码:

bool比特(无符号字符字节,整数索引)
{
返回(字节>>索引)&1;
}

我认为不太可能在编译器中一个字节一个字节地确定等效版本,有些细微的差异不值得担心。接下来,请确保使用正确的标志进行编译。试图让两个编译器产生相同的输出可能是徒劳的。

上一次我写了一个32位比特的编译器,它看起来像这样(64位看起来有点不同):

虽然如果你想把它放在一个公共标题中,我有一个不同的版本。当我使用-O2时,它最终将整个东西内联起来,以生成真正高效的代码


我很惊讶gcc本身没有生成btl(请参阅),但您是对的,它没有生成btl。

如果您想生成完全相同的代码,那么您可以执行以下操作

const char bittestfunction[] = { 0xf, 0xa3, 0xf7, 0xf, 0x92, 0xc0, 0x3 };
int (*bittest)( unsigned char, int ) = (int(*)(unsigned char, int))bittestfunction;
您可以用同样的方式调用它
bitest(foo,bar)

从(gcc)编译的可执行文件上的
objdump

00000000004006cc <bittestfunction>:
  4006cc:       0f a3 f7                bt     %esi,%edi
  4006cf:       0f 92 c0                setb   %al
  4006d2:       c3                      retq
0000000000 4006cc:
4006cc:0f a3 f7 bt%esi,%edi
4006cf:0f 92 c0后退%al
4006d2:c3 retq

我和Patrick在一起,你打了一个不好的电话,试图完全匹配clang。您可以简单地执行asm(“btl%esi,%edi\nsetb%al\nret”),但您几乎肯定会后悔。如果你决定你愿意探索合理的选择,我有一些。另外,如果您打算使用内联asm,是否签出了新文档?它们最近被重新编写。它们组织得更好,并且包含许多示例:那么GCC生成了什么呢?你确定它至少没有那么好吗?你问的是一个关于编程细节的问题,而没有给出更大目标的提示。您是否在优化性能?按位正确性?只是为了学习?还是完全不同的原因?这可能会严重影响给出的答案-目前我不知道您的目标是什么以及什么是可接受的答案。@Matstpeterson更新了我的问题。@KlaasvanGend我实际上无法访问本地的Clang atm副本,只有MinGW。我想比较一下性能。这没有用,因为它没有内联。这个问题真正想要的是一个内联asm版本,它可以内联。更糟糕的是,这必须通过函数指针(使用间接的
调用
)来调用,因为您将其作为数据写入,而不是在asm中编写一个可以正常链接的独立函数。从
Base
中删除
“m”
替代项将是一种优化。现代CPU上的x86内存位字符串指令比某些地址数学+a load+
bt r,r
慢得多(比如~10 uops)。我想这取决于释放寄存器的成本。如果gcc有一个临时寄存器,您可能是对的。如果它必须刷新/重新加载某些内容,可能不会。IAC,我想我从未见过gcc在指定“rm”时使用“m”。但是如果我要更新这个旧答案,我会更倾向于添加@cc内容,而不是使用
setc
00000000004006cc <bittestfunction>:
  4006cc:       0f a3 f7                bt     %esi,%edi
  4006cf:       0f 92 c0                setb   %al
  4006d2:       c3                      retq