我以为因为条件是> = 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/