gpt4 book ai didi

gcc - 在 GCC 内联汇编中检索 ZF

转载 作者:行者123 更新时间:2023-12-02 20:56:05 28 4
gpt4 key购买 nike

我需要使用一些没有 GCC 内在函数的 x86 指令,例如 BSF 和 BSR。使用 GCC 内联汇编,我可以编写如下内容

__INTRIN_INLINE unsigned char bsf64(unsigned long* const index, const uint64_t mask)
{
__asm__("bsf %[mask], %[index]" : [index] "=r" (*index) : [mask] "mr" (mask));
return mask ? 1 : 0;
}

类似 if (bsf64(x, y)) {/* use x */} 的代码被 GCC 翻译为类似的内容

0x000000010001bf04 <bsf64+0>:   bsf    %rax,%rdx
0x000000010001bf08 <bsf64+4>: test %rax,%rax
0x000000010001bf0b <bsf64+7>: jne 0x10001bf44 <...>

但是,如果mask为零,则BSF已经设置了ZF标志,因此bsf之后的test是多余的。

而不是返回 mask ? 1 : 0,是否可以检索ZF标志并返回它,使GCC不生成测试

编辑:使 if 示例更加清晰

编辑:响应 Damon,__builtin_ffsl 生成的代码甚至不太理想。如果我使用以下代码

    int b = __builtin_ffsl(mask);
if (b) {
*index = b - 1;
return true;
} else {
return false;
}

GCC 生成此程序集

   0x000000000044736d <+1101>:  bsf    %r14,%r14
0x0000000000447371 <+1105>: cmove %r12,%r14
0x0000000000447375 <+1109>: add $0x1,%r14d
0x0000000000447379 <+1113>: je 0x4471c0 <...>
0x000000000044737f <+1119>: lea -0x1(%r14),%ecx

因此,测试消失了,但生成了冗余的条件移动、增量和减量。

最佳答案

几点说明:

  • 这是一种“反优化”。您正在尝试对编译器已支持的内容进行微优化。
  • 使用我的 gcc 版本并打开所有优化开关,您的代码根本不会生成 bsf 指令。查看代码,这并不奇怪,因为您返回 mask,它是操作数,而不是目标操作数(gcc 使用 AT&T 语法!)。编译器足够智能,可以解决这个问题,并完全删除汇编代码(它不执行任何操作)。
  • 有一个内部函数__builtin_ffsl,它的作用与内联程序集完全相同(尽管是正确的)。内在函数的可移植性并不比内联汇编程序差,但编译器更容易优化。
  • 使用内部函数会在我的编译器上产生 bsf cmov 序列(假设调用代码强制它实际发出指令),这表明编译器可以很好地使用零标志,而无需额外的测试说明。
  • 当你想要一个 bool 时返回一个 char 对于编译器来说并不是最好的提示,尽管它在大多数情况下可能会弄清楚。然而,当您实际上只对“零或非零”感兴趣时,告诉编译器使用位扫描指令肯定不是最佳选择。 if(x)if(!x) 在这方面工作得非常好。如果您返回结果作为引用,情况会有所不同,因此您可以在其他地方重用它,但事实上,您的代码只是一种非常复杂的 if(x) 编写方式。<

关于gcc - 在 GCC 内联汇编中检索 ZF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6895714/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com