理解if(a> = 3)的gcc输出

时间:2017-09-25 18:59:16

标签: c gcc assembly x86

enter image description here

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

但是gcc使用jle(更少或相等)。

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

2 个答案:

答案 0 :(得分:6)

您通过编译器在从C源到asm实现的过程中所做的转换而变得混乱。 gcc的输出以这种方式实现你的功能:

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

ret0:
return 0;

由于您使用-O0进行编译,所以它都很笨重和冗余,所以它将a存储到内存然后重新加载它,因此如果设置断点,可以使用调试器对其进行修改并且仍然有代码&#34; work&#34;。

另见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,比较和条件在英特尔语法中有意义,但在AT&amp; T语法中是倒退的。例如,如果cmp edi, 127,则会jg / edi > 127

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

答案 1 :(得分:3)

汇编代码将a与两个而不是三个进行比较。这就是它使用jle的原因。如果a小于或等于2,则逻辑上遵循IS不大于或等于3,因此应返回0