繁体   English   中英

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

[英]Understanding gcc output for if (a>=3)

在此处输入图片说明

我想既然条件是 >= 3,我们应该使用jl (less)。

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

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

你被编译器在从 C 源代码到 asm 实现的过程中所做的转换混淆了。 gcc 的输出以这种方式实现您的功能:

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

ret0:
return 0;

这一切都是笨重和冗余的,因为您使用-O0编译,因此它将a存储到内存然后重新加载它,因此如果您设置了断点并且仍然使代码“工作”,则可以使用调试器修改它。

另请参阅如何从 GCC/clang 程序集输出中去除“噪音”?


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

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

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

Godbolt 上的gcc -O3 ,针对 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编码(英特尔手册中 Intel 语法中的cmp r/m32, imm8 ),但是 128 就必须使用cmp $imm32, r/m32

顺便说一句,比较和条件在 Intel 语法中有意义,但在 AT&T 语法中是倒退的。 例如,如果edi > 127则采用cmp edi, 127 / jg

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

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

暂无
暂无

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

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