Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use JLE instead of JL?

I wrote the following program:

#include <stdio.h>

int main()
{
    int i = 0;
    for (; i < 4; i++)
    {
        printf("%i",i);
    }

    return 0;
} 

I compiled it using gcc test.c -o test.o, then disassembled it using objdump -d -Mintel test.o. The assembly code I got (at least the relevant part) is the following:

0804840c <main>:
 804840c:   55                      push   ebp
 804840d:   89 e5                   mov    ebp,esp
 804840f:   83 e4 f0                and    esp,0xfffffff0
 8048412:   83 ec 20                sub    esp,0x20
 8048415:   c7 44 24 1c 00 00 00    mov    DWORD PTR [esp+0x1c],0x0
 804841c:   00 
 804841d:   eb 19                   jmp    8048438 <main+0x2c>           
 804841f:   8b 44 24 1c             mov    eax,DWORD PTR [esp+0x1c]
 8048423:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048427:   c7 04 24 e8 84 04 08    mov    DWORD PTR [esp],0x80484e8
 804842e:   e8 bd fe ff ff          call   80482f0 <printf@plt>
 8048433:   83 44 24 1c 01          add    DWORD PTR [esp+0x1c],0x1
 8048438:   83 7c 24 1c 03          cmp    DWORD PTR [esp+0x1c],0x3
 804843d:   7e e0                   jle    804841f <main+0x13>
 804843f:   b8 00 00 00 00          mov    eax,0x0
 8048444:   c9                      leave  
 8048445:   c3                      ret

I noticed that, although my compare operation was i < 4, the assembly code is (after disassembly) i <= 3. Why does that happen? Why would it use JLE instead of JL?

like image 358
elyashiv Avatar asked Oct 24 '13 17:10

elyashiv


1 Answers

Loops that count upwards, and have constant limit, are very common. The compiler has two options to implement the check for loop termination - JLE and JL. While the two ways seem absolutely equivalent, consider the following.

As you can see in the disassembly listing, the constant (3 in your case) is encoded in 1 byte. If your loop counted to 256 instead of 4, it would be impossible to use such an efficient encoding for the CMP instruction, and the compiler would have to use a "larger" encoding. So JLE provides a marginal improvement in code density (which is ultimately good for performance because of caching).

like image 51
anatolyg Avatar answered Sep 19 '22 23:09

anatolyg