Assembler construct to compare a variable with a constant:
cmp rN, #n // compares rN with n, setup flags blt label // If the flags indicate that ( rN < n ) // then branch to label next-instr // Otherwise, continue here with the "next-instr" .... .... label: |
Assembler construct to compare a variable with a another variable:
cmp rN, rM // compares rN with rM, setup flags blt label // If the flags indicate that ( rN < rM ) // then branch to label next-instr // Otherwise, continue here with the "next-instr" .... .... label: |
The same explanation applies with the other conditional branch instructions !
We can combinate any one of the 2 compare instructions with any one of the 6 conditional branch instructions:
Combine: cmp rN, #n // compares rN with n // sets the flags according to comparison cmp rN, rM // compares rN with rM // sets the flags according to comparison with: beq label // if ( rN == {n or rM} ) branch to label bne label // if ( rN != {n or rM} ) branch to label blt label // if ( rN < {n or rM} ) branch to label ble label // if ( rN <= {n or rM} ) branch to label bgt label // if ( rN > {n or rM} ) branch to label bge label // if ( rN >= {n or rM} ) branch to label |
Furthermore, there is an unconditional branch instruction b label that always branches to the location label.
The inverse of the comparison operations:
Comparison Inverse "In other words" ----------------------------------------------------- x == y x != y !(x == y) ≡ x != y x != y x == y !(x != y) ≡ x == y x < y x >= y !(x < y) ≡ x >= y x <= y x > y !(x <= y) ≡ x > y x > y x <= y !(x > y) ≡ x <= y x >= y x < y !(x >= y) ≡ x < y |
Reason:
|
|
Flow chart of the if-statement if ( condition ) ----> | { | statement(s); +--------------+ FALSE } | condition |--------+ +--------------+ | | | | TRUE | | | V | statement(s) | | | | | V | +<---------------+ | V |
|
Assembler code that implements the program flow specified by an if-statement:
Assembler codes to evaluate "condition" (use cmp instruction) | V FALSE Branch on FALSE outcome of "condition" to label L: ----+ | | | (True) | | | V | Assembler codes to execute "statement(s)" | | | | | V | L: +<----------------------------------------+ | V |
I will illustrate the translation process with an example...
Example if-statement:
int x; if ( x < 0 ) x = -x; |
For
brevity,
I will
omit the
variable definition
from now on
because we have seen such
definition many times
already...
If-statement in a high level language:
if ( x < 0 ) x = -x; |
The corresponding flow chart for this if-statement is:
The branch condition is NOT ( x < 0 ) ≡ ( x >= 0 ) - now translate into assembler !
main:
movw r0, #:lower16:x
movt r0, #:upper16:x // r0 = addr(x)
ldr r0, [r0] // r1 = x
cmp r0, #0 // Compare x against 0
bge IfEnd // if (x >= 0) skip "x=-x" to ifEnd
// x = -x;
movw r0, #:lower16:x
movt r0, #:upper16:x // r0 = addr(x)
ldr r1, [r0] // r1 = value in x
neg r1, r1 // r1 = value -x
str r1, [r0] // Update variable x with the value r0=-x
IfEnd:
.data
x: .4byte -4 // x = -4 -- try +4 also
.end
|
DEMO: /home/cs255001/demo/asm/6-if/if1.s
main: movw r0, #:lower16:x movt r0, #:upper16:x // r0 = addr(x) ldr r1, [r0] // r1 = x cmp r1, #0 // Compare x ? 0 bge IfEnd // Branch to "ifEnd" if x >= 0 // (We don't need to fetch x, since r1 = x ! neg r1, r1 // r1 = 0 - r1 (negate) // Note: r0 still contains addr(x) ! str r1, [r0] // Update x with -x in r0 IfEnd: .data x: .4byte -4 // x = -4 -- try +4 also .end |
I do not recommend/require that you optimize (because it's more error prone)
Example 2: making sure that x ≤ y:
int x; int y; int help; // If-statement to make sure: x ≤ y if ( x > y ) // This is the classic "swap(x,y)" algorithm { help = x; x = y; y = help; } |
Comment: this if-statement is part of the Bubble Sort algorithm
if ( x > y )
{
help = x; // Swap x and y
x = y;
y = help;
}
|
The corresponding flow chart for this if-statement is:
Note: in assembler code, you do not need the help variable to swap (use registers instead) !
main:
// Test if ( x > y )
movw r0, #:lower16:x
movt r0, #:upper16:x // r0 = addr(x)
ldr r0, [r0] // r0 = x
movw r1, #:lower16:y
movt r1, #:upper16:y // r1 = addr(y)
ldr r1, [r1] // r1 = y
cmp r0, r1 // Compare x ? y
ble ifEnd // Branch if x <= y to ifEnd
/* ------------- swap x and y ------------------------ */
// Get addr x and value in x
movw r0, #:lower16:x
movt r0, #:upper16:x // r0 = addr(x)
ldr r1, [r0] // r1 = x
// Get addr y and value in y
movw r2, #:lower16:y
movt r2, #:upper16:y // r2 = addr(y)
ldr r3, [r2] // r3 = y
str r3, [r0] // Update x with the value of y
str r1, [r2] // Update y with the value of x
ifEnd:
/* --------------------------------------------------
Begin of the permanent program variables
-------------------------------------------------- */
.data
x: .4byte 9 // x = 9 -- try a value smaller that 4
y: .4byte 4 // y = 4
.end
|
DEMO: /home/cs255001/demo/asm/6-if/if2.s
main:
movw r0, #:lower16:x
movt r0, #:upper16:x // r0 = addr(x)
ldr r1, [r0] // r1 = value of x
movw r2, #:lower16:y
movt r2, #:upper16:y // r2 = addr(y)
ldr r3, [r2] // r3 = value of y
cmp r1, r3 // Compare x against y
ble ifEnd // if ( x <= y ) branch to ifEnd
// Swap x and y using values of x and y in R1 and R3
str r3, [r0] // var x in memory = copy of y in R3
str r1, [r2] // var y in memory = copy of x in R1
ifEnd:
/* --------------------------------------------------
Begin of the permanent program variables
-------------------------------------------------- */
.data
x: .4byte 9 // x = 9 -- try a value smaller that 4
y: .4byte 4 // y = 4
.end
|
DEMO: /home/cs255001/demo/asm/6-if/if3.s