You're getting mixed up by a transformation the compiler made on the way from the C source to the asm implementation. gcc's output implements your function this way:
a = 5;
if (a<=2) goto ret0;
return 1;
ret0:
return 0;
It's all clunky and redundant because you compiled with -O0
, so it stores a
to memory and then reloads it, so you could modify it with a debugger if you set a breakpoint and still have the code "work".
See also How to remove "noise" from GCC/clang assembly output?
Compilers generally prefer to reduce the magnitude of a comparison constant , so it's more likely to fit in a sign-extended 8-bit immediate instead of needing a 32-bit immediate in the machine code.
We can get some nice compact code by writing a function that takes an arg, so it won't optimize away when we enable optimizations.
int cmp(int a) {
return a>=128; // In C, a boolean converts to int as 0 or 1
}
gcc -O3
on Godbolt , targetting the x86-64 ABI (same as your code):
xorl %eax, %eax # whole RAX = 0
cmpl $127, %edi
setg %al # al = (edi>127) : 1 : 0
ret
So it transformed a >=128
into a >127
comparison. This saves 3 bytes of machine code, because cmp $127, %edi
can use the cmp $imm8, r/m32
encoding ( cmp r/m32, imm8
in Intel syntax in Intel's manual ), but 128 would have to use cmp $imm32, r/m32
.
BTW, comparisons and conditions make sense in Intel syntax, but are backwards in AT&T syntax. For example, cmp edi, 127
/ jg
is taken if edi > 127
.
But in AT&T syntax, it's cmp $127, %edi
, so you have to mentally reverse the operands or think of a >
instead of <
The assembly code is comparing a
to two, not three. That's why it uses jle
. If a
is less than or equal to two it logically follows that a IS NOT greater than or equal to 3, and therefore 0
should be returned.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.