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 theFLAGS
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 theOF
(overflow) bit of theFLAGS
.- 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 thusjge
would be false.
- If x > y, then
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