[英]Understanding gcc output for if (a>=3)
你被编译器在从 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.