Conditionals

If Statements

In this section we'll see how if statements are rendered in assembly.

Single If

We define a function less_than() which returns 1 if x is less than y, otherwise it returns 0.

int less_than(int x, int y) {
    if (x < y) {
        return 1;
    }

    return 0;
}

Following the function prologue, the parameters are moved on to the stack. The value in x is then moved back into eax.

The if statement starts with the cmp instruction. This instruction takes two parameters and performs a comparison. This comparison actually consists of a signed subtraction of the subtrahend (the first parameter) from the minuend (the second parameter). The result is not stored, but the FLAGS register is set in the same manner as the sub instruction. These flags are then used in the following jump instructions. In our case the cmp instruction is equivalent to x - y.

The jge instruction (jump greater than or equal to) jumps to the memory location specified if the first parameter of cmp was greater than or equal to the second parameter of cmp. It does this by checking:

  • If the ZF (zero flag) bit of the FLAGS register is 1. This flag would be set if both arguments were the same value.
  • If the SF (sign flag) bit has the same value as the OF (overflow) bit of the FLAGS.
    • If x > y, then SF won't be set.
    • But there could be the case where y > x, but y is so big that it underflows and SF is still not set.
    • In this instance, the OF would be set, SF != OF and thus jge would be false.

If x is greater than or equal to y, the eip instruction pointer register is loaded with the memory location of .L2. In this case the eax register - where the function return value is placed - is loaded with the value 0. If x is less than y, control falls through to the next statement, which loads 1 into eax. The jmp .L3 instruction then unconditionally loads the eip register with the memory value of the .L3 label.

The previously base pointer is popped off the stack, and the function returns.

less_than:
    push    rbp
    mov    rbp, rsp
    mov    DWORD PTR [rbp-4], edi
    mov    DWORD PTR [rbp-8], esi
    mov    eax, DWORD PTR [rbp-4]
    cmp    eax, DWORD PTR [rbp-8]
    jge    .L2
    mov    eax, 1
    jmp    .L3
.L2:
    mov    eax, 0
.L3:
    pop    rbp
    ret

Logical Or

We now look at how multiple boolean conditions are groups together using a logical or. Our function tests whether x equals y in a less-than-optimal way by testing whether x is less than or x is greater than y.

int roundabout_equals(int x, int y) {
    if (x < y || x > y) {
        return 0;
    }
    return 1;
}

Following the function prologue, x is moved from the stack into the eax register and compared with y (which is still on the stack at rbp-8). The jl instruction tests whether than SF != OF, which is the same as the jle discussed previously but without the ZF flag check. If x is less than y, then the program flow moves to label .L2, where 0 is loaded into eax. The program flow then jumps to .L4 where the function epilogue and the function returns.

If x is not less than y, x is again moved from the stack to eax and compared against the y value on the stack. The jle instruction then tests whether x is less than or equal to y. If it is then the program jumps to .L3 where 1 is loaded into the eax register.

roundabout_equals:
    push    rbp
    mov    rbp, rsp
    mov    DWORD PTR [rbp-4], edi
    mov    DWORD PTR [rbp-8], esi
    mov    eax, DWORD PTR [rbp-4]
    cmp    eax, DWORD PTR [rbp-8]
    jl    .L2
    mov    eax, DWORD PTR [rbp-4]
    cmp    eax, DWORD PTR [rbp-8]
    jle    .L3
.L2:
    mov    eax, 0
    jmp    .L4
.L3:
    mov    eax, 1
.L4:
    pop    rbp
    ret

Logical And

int both_not_zero(int x, int y) {
    if (x != 0 && y != 0) {
        return 1;
    }

    return 0;
}
both_not_zero:
    push    rbp
    mov    rbp, rsp
    mov    DWORD PTR [rbp-4], edi
    mov    DWORD PTR [rbp-8], esi
    cmp    DWORD PTR [rbp-4], 0
    je    .L2
    cmp    DWORD PTR [rbp-8], 0
    je    .L2
    mov    eax, 1
    jmp    .L3
.L2:
    mov    eax, 0
.L3:
    pop    rbp
    ret

If / Else If / Else

int compare(int x, int y) {
    if (x < y) {
        return -1;
    } else if (x == y) {
        return 0;
    } else {
        return 1;
    }
}
compare:
    push    rbp
    mov    rbp, rsp
    mov    DWORD PTR [rbp-4], edi
    mov    DWORD PTR [rbp-8], esi
    mov    eax, DWORD PTR [rbp-4]
    cmp    eax, DWORD PTR [rbp-8]
    jge    .L2
    mov    eax, -1
    jmp    .L3
.L2:
    mov    eax, DWORD PTR [rbp-4]
    cmp    eax, DWORD PTR [rbp-8]
    jne    .L4
    mov    eax, 0
    jmp    .L3
.L4:
    mov    eax, 1
.L3:
    pop    rbp
    ret

results matching ""

    No results matching ""