简体   繁体   English

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

[英]How to implement this in inline assembly?

I'm woefully bad at understanding the GNU inline assembly syntax, so I'm hoping a practical example may help. 我非常无法理解GNU内联汇编语法,所以我希望有一个实际的例子可能会有所帮助。 Given the following assembly (x86-64, output by Clang) how would I construct a function using inline assembly that would be identical? 给定以下程序集(x86-64,Clang输出),我将如何使用相同的内联程序集构造函数? GCC produces different code for the same function and I would like to get it to produce an identical version to what Clang (-O3) outputs. GCC为相同的功能生成了不同的代码,我想让它生成与Clang(-O3)输出相同的版本。

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

Here is what GCC (-O3) is producing: 这是GCC(-O3)产生的:

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

Here is the C code for the function: 这是该函数的C代码:

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

Well, last time I wrote a 32bit bittest, it looked something like this (the 64bit looks slightly different): 好吧,上一次我编写了一个32bit的比特测试,看起来像这样(64bit看起来略有不同):

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; 
}

Although if you want to put it in a public header, I have a different version. 尽管如果您想将其放在公共标题中,则可以使用其他版本。 When I use -O2, it ends up inlining the whole thing to make really efficient code. 当我使用-O2时,它最终会内联整个内容,以制作出真正有效的代码。

I'm surprised gcc doesn't generate the btl here itself (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36473 ), but you are right it doesn't. 令我惊讶的是,gcc本身不会在其中生成btl(请参阅https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36473 ),但您说的却不是。

I think it's unlikely that you can nail down a byte-by-byte equivalent version in your compiler, there are minor differences that aren't worth worrying about. 我认为您不太可能在编译器中确定一个逐字节的等效版本,其中有一些细微的差异是不值得担心的。 Following this question , make sure you're compiling with the correct flags. 遵循这个问题 ,请确保您使用正确的标志进行编译。 Trying to get two compilers to produce identical output is probably an exercise in futility. 试图让两个编译器产生相同的输出可能是徒劳的。

If you want to generate the exact same code then you can do the following 如果要生成完全相同的代码,则可以执行以下操作

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

You can call this in the same way bittest( foo, bar ) . 您可以使用bittest( foo, bar )相同的方式来调用它。

From objdump on the (gcc) compiled executable 从(gcc)编译的可执行文件上的objdump

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

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

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