我对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;
}
发布于 2014-06-03 21:38:43
好吧,上次我写了一个32位的位测试,它看起来像这样(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),但你是对的,它没有。
发布于 2014-06-03 02:53:25
我认为你不太可能在你的编译器中确定一个逐字节等价的版本,有一些细微的差异不值得担心。在this question之后,确保使用正确的标志进行编译。尝试让两个编译器产生相同的输出可能是徒劳的。
发布于 2016-08-06 06:23:39
如果您希望生成完全相同的代码,则可以执行以下操作
const char bittestfunction[] = { 0xf, 0xa3, 0xf7, 0xf, 0x92, 0xc0, 0x3 };
int (*bittest)( unsigned char, int ) = (int(*)(unsigned char, int))bittestfunction;
您可以使用与bittest( foo, bar )
相同的方式调用它。
从objdump
谈(gcc)编译后的可执行文件
00000000004006cc <bittestfunction>:
4006cc: 0f a3 f7 bt %esi,%edi
4006cf: 0f 92 c0 setb %al
4006d2: c3 retq
https://stackoverflow.com/questions/24006329
复制