答案 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
。
cmp edi, 127
,则会jg
/ edi > 127
。
但在AT&amp; T语法中,它是cmp $127, %edi
,因此您必须在心理上反转操作数或考虑>
而不是<
答案 1 :(得分:3)
汇编代码将a
与两个而不是三个进行比较。这就是它使用jle
的原因。如果a
小于或等于2,则逻辑上遵循IS不大于或等于3,因此应返回0
。