c - 了解if(a> = 3)的gcc输出-LMLPHP

我以为因为条件是> = 3,所以我们应该使用jl(更少)。

但是gcc使用了jle(小于或等于)。

对我来说这没有意义;编译器为什么要这样做?

最佳答案

编译器在从C源代码到asm实现的过程中所做的转换使您感到困惑。 gcc的输出通过以下方式实现您的功能:

a = 5;
if (a<=2) goto ret0;
return 1;

ret0:
return 0;


这都是笨拙且多余的,因为您使用-O0进行了编译,因此它将a存储到内存中,然后重新加载它,因此,如果您设置了断点并且仍然具有代码“ work”,则可以使用调试器对其进行修改。

另见How to remove "noise" from GCC/clang assembly output?



编译器通常更喜欢减小比较常数的大小,因此它更有可能适合使用符号扩展的8位立即数,而不需要在机器代码中使用32位立即数。

我们可以通过编写一个带有arg的函数来获得一些精巧的紧凑代码,因此在启用优化后它不会被优化。

int cmp(int a) {
    return a>=128;   // In C, a boolean converts to int as 0 or 1
}


gcc -O3 on Godbolt,定位x86-64 ABI(与您的代码相同):

    xorl    %eax, %eax           # whole RAX = 0
    cmpl    $127, %edi
    setg    %al                  # al = (edi>127) : 1 : 0
    ret


因此,它将>=128转换为>127比较。这样可以节省3个字节的机器代码,因为cmp $127, %edi可以使用cmp $imm8, r/m32编码(cmp r/m32, imm8 in Intel syntax in Intel's manual),但是128个必须使用cmp $imm32, r/m32

BTW,比较和条件在Intel语法中很有意义,但在AT&T语法中却是倒退。例如,如果cmp edi, 127,则采用jg / edi > 127

但是在AT&T语法中,它是cmp $127, %edi,因此您必须在思维上反转操作数或考虑使用>而不是<

关于c - 了解if(a> = 3)的gcc输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46412381/

10-13 03:01