-4

enter image description here

I thought since condition is a >= 3, we should use jl (less).

But gcc used jle (less or equal).

It make no sense to me; why did the compiler do this?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
James
  • 39
  • 2
  • 9

2 Answers2

7

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 <

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
3

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.

machine_1
  • 4,266
  • 2
  • 21
  • 42
JMcCoy
  • 306
  • 2
  • 6