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

时间:2014-06-03 02:45:23

标签: c++ assembly x86-64 inline-assembly

我很难理解GNU内联汇编语法,所以我希望一个实际的例子可能有所帮助。鉴于以下程序集(x86-64,Clang的输出),我将如何使用内联汇编构造一个相同的函数? GCC为同一个函数生成不同的代码,我想让它生成与Clang(-O3)输出相同的版本。

bittest(unsigned char, int):
    btl %esi, %edi
    setb    %al
    ret

以下是GCC(-O3)正在制作的内容:

bittest(unsigned char, int):
    movzx    eax, dil
    mov    ecx, esi
    sar    eax, cl
    and    eax, 1
    ret

以下是该函数的C代码:

bool bittest(unsigned char byte, int index)
{
    return (byte >> index) & 1;
}

3 个答案:

答案 0 :(得分:2)

好吧,上次我写了一个32位bittest,它看起来像这样(64位看起来略有不同):

unsigned char _bittest(const long *Base, long Offset) 
{ 
   unsigned char old; 
   __asm__ ("btl %[Offset],%[Base] ; setc %[old]" : 
      [old] "=rm" (old) : 
      [Offset] "Ir" (Offset), [Base] "rm" (*Base) : 
      "cc"); 

   return old; 
}

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

我很惊讶gcc本身并没有生成btl(参见https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36473),但是你没有。

答案 1 :(得分:1)

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

答案 2 :(得分:-1)

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

const char bittestfunction[] = { 0xf, 0xa3, 0xf7, 0xf, 0x92, 0xc0, 0x3 };
int (*bittest)( unsigned char, int ) = (int(*)(unsigned char, int))bittestfunction;

您可以采用与bittest( foo, bar )相同的方式拨打此电话。

来自(gcc)已编译可执行文件的objdump

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