[Example] Conditionals in Assembly
Conditionals1
(version 1, compare at each branch similar to what you see in Java)
// Program to show how to use if/else-if/else inside a loop
// Loops 10 times: say if the current loop# is less than, greater than, or exactly 5.
// Define format string for call to printf()
less: .string "Loop #%d: %d is less than 5.\n"
greater:.string "Loop #%d: %d is greater than 5.\n"
equal: .string "Loop #%d: Exactly 5! (Ya I know this program's stupid too.)\n"
// Define the main function for our program
.balign 4 // Instructions must be word aligned
.global main // Make "main" visible to the OS
main: stp x29, x30, [sp, -16]! // Save frame pointer (fp, x29) and link register (lr, x30) to stack, allocating 16 bytes, pre-increment SP
mov x29, sp // Update frame pointer (fp) to current stack pointer (sp) (after we've incremented sp in the last step)
mov x19, 1 // Set x19 general purpose register to 0, this will be the loop counter
// While loop (pre-test, so check before the first iteration)
// Let's loop 10 times, printing out each number.
test: cmp x19, 10 // Compare loop counter and 10
b.gt done // If [loop counter]>10, exit loop and branch to "done"
// Start of code inside the loop
// If loop# < 5
cmp x19, 5
b.ge elseif // If loop# >=5, then condition is NOT satifsied, move to next if (elseif)
adrp x0, less // Set the 1st argument of printf(fmt, var1, var2...) (high-order bits)
add x0, x0, :lo12:less // Set the 1st argument of printf(fmt, var1, var2...) (lower 12 bits)
mov x1, x19 // Set the 2nd argument of printf().
// We are adding one, then saving it to x1 register as 2nd argument
// This is just to print 1-10, instead of 0-9
mov x2, x1 // Set the 3rd argument of printf().
b next // Since
// Else-if loop# > 5
elseif: cmp x19, 5
b.le else // If loop# <=5, then condition is NOT satifised, move to next part (else)
adrp x0, greater
add x0, x0, :lo12:greater
mov x1, x19
mov x2, x1
b next
// Else (loop# == 5)
else: adrp x0, equal // Else catches everything else, if it reaches here then just proceed, no need to compare
add x0, x0, :lo12:equal
mov x1, x19
// In the conditionals we set the arguments for printf(), so let's call it now.
next: bl printf // Call the printf() function
// End of code inside the loop
add x19, x19, 1 // Increment loop counter by 1
b test
// Return 0 in main, like we did in C
done: mov w0, 0
// Restore registers and return to calling code (OS)
ldp x29, x30, [sp], 16 // Restore fp and lr from stack, post-increment sp
ret // Return to caller
Conditionals2
(version 2, compare once, then either fall through to first case or branch to second/third cases. There are three cases because two operands are either >, <, or =.)
// Program to show how to use if/else-if/else inside a loop
// Loops 10 times: say if the current loop# is less than, greater than, or exactly 5.
// Define format string for call to printf()
less: .string "Loop #%d: %d is less than 5.\n"
greater:.string "Loop #%d: %d is greater than 5.\n"
equal: .string "Loop #%d: Exactly 5! (Ya I know this program's stupid too.)\n"
// Define the main function for our program
.balign 4 // Instructions must be word aligned
.global main // Make "main" visible to the OS
main: stp x29, x30, [sp, -16]! // Save frame pointer (fp, x29) and link register (lr, x30) to stack, allocating 16 bytes, pre-increment SP
mov x29, sp // Update frame pointer (fp) to current stack pointer (sp) (after we've incremented sp in the last step)
mov x19, 1 // Set x19 general purpose register to 0, this will be the loop counter
// While loop (pre-test, so check before the first iteration)
// Let's loop 10 times, printing out each number.
test: cmp x19, 10 // Compare loop counter and 10
b.gt done // If [loop counter]>10, exit loop and branch to "done"
// Start of code inside the loop
// If loop# < 5
cmp x19, 5
b.gt elseif // If loop# > 5, then condition is NOT satifsied, move to elseif (loop# >5)
b.eq else // If loop# == 5, then condition is NOT satifsied, move to else (loop# == 5)
adrp x0, less // Set the 1st argument of printf(fmt, var1, var2...) (high-order bits)
add x0, x0, :lo12:less // Set the 1st argument of printf(fmt, var1, var2...) (lower 12 bits)
mov x1, x19 // Set the 2nd argument of printf().
// We are adding one, then saving it to x1 register as 2nd argument
// This is just to print 1-10, instead of 0-9
mov x2, x1 // Set the 3rd argument of printf().
b next // Since
// Else-if loop# > 5
elseif: adrp x0, greater
add x0, x0, :lo12:greater
mov x1, x19
mov x2, x1
b next
// Else (loop# == 5)
else: adrp x0, equal // Else catches everything else, if it reaches here then just proceed, no need to compare
add x0, x0, :lo12:equal
mov x1, x19
// In the conditionals we set the arguments for printf(), so let's call it now.
next: bl printf // Call the printf() function
// End of code inside the loop
add x19, x19, 1 // Increment loop counter by 1
b test
// Return 0 in main, like we did in C
done: mov w0, 0
// Restore registers and return to calling code (OS)
ldp x29, x30, [sp], 16 // Restore fp and lr from stack, post-increment sp
ret // Return to caller