Programming - Assembly Branches and Jumps

    With this funny, but yet describing picture we start out today's post! Today, we will take a look at Code Branches and Jumps that let us jump from one line to another inside of our code using conditions or directly. Using them we will be able to create if/else statements (even switch case) or for/while loops! So, without further do, let's get started!


Jumps:

    With jumps we can directly go to another line of our dode, without checking any condition! There are also some other jumps that let us jump to a register based address or even run a function ( we will talk about them when we get into functions ) .

This jump instruction is written like that:

j Label, where the Label indicates a Label ( like main: ) that we set up at some point of our Code. 

    So, we could run some instructions put a jump instruction and then this code could be run again and again to create a loop or we could put it somewhere else in the Code ( similar to the "banned" go to in C ) to run other Code "skipping" some instructions.

An infinite Loop could be done like that:

Loop:
# instructions
j Loop

Having no branch statement inside that gets us out, this Code will be run forever!


Branches:

    With Branches we do a similar behavior to Jumps, but only when a condition is met. So, we will jump to the Label or continue running our Code as is. This way we can branch our Code, so that specific things are being runned, when specific conditions are met. 

Those branch instructions are the following:

  • beq $t0, $t1, Label -> Jump to Label when $t0 == $t1
  • bne $t0, $t1, Label -> Jump to Label when $t0 < $t1
  • blt $t0, $t1, Label -> Jump to Label when $t0 < $t1
  • ble $t0, $t1, Label -> Jump to Label when $t0 <= $t1
  • bgt $t0, $t1, Label -> Jump to Label when $t0 > $t1
  • bge $t0, $t1, Label -> Jump to Label when $t0 >= $t1
  • beqz $t0, Label -> Jump to Label when $t0 == 0

There are also some other ones, but these are the ones that are more than enough for the stuff that we will talk about!

    Suppose we want to increment the value of the first of the two registers by 1, only when the two registers have the same value, else we will decrease the one of the second one. Let's have the registers $t0 and $t1 have a value of 4 each and increment $t0 when they have the same value and decrease $t0 when they don't. 

This Code looks like that:

# initialize registers to 4
li $t0, 4
li $t1, 4
# check condition
beq $t0, $t1, Same
# not same
addi $t1, $t1, -1 # decrease second one by 1
j End
Same:
addi $t0, $t0, 1 # increase first one by 1
End:


We could also set it up in the opposite way checking if they are not equal like that:

# initialize registers to 4
li $t0, 4
li $t1, 4
# check condition
bne $t0, $t1, NotSame
# same
addi $t0, $t0, 1 # increase first one by 1
j End
NotSame:
addi $t1, $t1, -1 # decrease second one by 1
End:

If we do it that or the other way is a coder preference!

If/else statement:

    Without noticing we created an if/else statement here! When they are equal we do this, when not the other!

So, an if/else if/else statement looks like that:

# check condition(s)
# else code
# Labels and code for if/else if conditions
# Ending Label to jump from all the others there

Using the same register in each condition check, we successfully have created an switch case statement then!


Loops:

    Loops work in the same exact way we did our infinite loop, but we will this time check every time we re-enter our Label if we surpassed the loop counter or if the condition is not met anymore!

So, our Code looks like this:

Label:
# check "opposite"/ending condition to finish loop by jumping to End
# instructions
j Label
End:


To create a simple for loop that goes from 0 to 10 we can use the following Code:

# initialize loop counter
li $t0, 0
For:
# check ending condition
bge $t0, 10, End
# instructions to be looped over and over
# increment loop counter
addi $t0, $t0, 1
j Label
End:


A while loop that stop when a specific register gets a specific value looks like that:

# initialize starting value
li $t0, 5
While:
# check condition
beq $t0, 7, End
# get integer input
li $v0, 5
syscall
# move to $t0 register
move $t0, $v0 
j While
End: 


    To create an do while loop you simply have to put the Code inside the Loop again before the loop or ( much better way ) check the condition before jumping like that:

DoWhile:
# instructions
# check condition that brings us to End
j DoWhile
End:


Other useful instructions:

slt:

    One pretty useful instruction that can help us a lot of times is called slt $d, $s, $t( Set on less than ) that sets the value of the $d register to 1, when $s < $t. Because, we can use arithmetic values and registers in all the branches, we can check a while condition using this sometimes when needed, simply checking if $d has the value 0 or 1!

    There are also other versions of this instruction called slti, sltiu, sltu that are used for immediate checking ( having last register be arithmetic value instead ), unsigned immediate checking ( having last register be arithmetic but only positive ) and checking unsigned register values. 


Arithmetic instructions:

    I already used some of them to initialize, increment, decrease register values, but this time I show you all that are useful for the stuff that we will do and for simple programms in generall.

The instructions we will use for the easy parts are:

  • add $t0, $t1, $t2 # t0 = t1 + t2
  • sub $t0, $t1, $t2 # t0 = t1 - t2
  • addi $t0, $t1, integer # t0 = t1 + integer
  • addu/subu $t0, $t1, $t2 # same as add/sub but for unsigned values
  • mul $t0, $t1, $t2 # $t0 = $t1 * $t2 (pseudo-instruction)
  • div $t0, $t1, $t2 # $t0 = $t1 / $t2 (pseudo-instruction)
  • rem $t0, $t1, integer # $t0 = $t1 % integers (pseudo-instruction)
  • sra, srl, sll # shifting right arithmetic, right logical, left logical
  • not, and, andi, or, ori, xor, xori # bitwise not, and, and immediate, or, or immediate, xor, xor immediate


Coding Section:

    We will use the second Code from last time and put it inside of a for loop and a while loop ( that checks a condition ) to run it more than one times. 

The Code from last time is:

Code 1:

We get two integer values as input, print them, swap them and print them again.

.data
# Constant strings to be output to the terminal
givex: .asciiz "x: "
givey: .asciiz "y: "
space: .asciiz " "
linefeed: .asciiz "\n"
end: .asciiz "End of Program!"

.text
main:
# print message for getting x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# get x as input
li $v0,5 # code for read_int
syscall #get int from user --> returned in $v0
move $t0,$v0 # move the resulting int to $t0

# print message for getting y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# get y as input
li $v0,5 # code for read_int
syscall # get int from user --> returned in $v0
move $t1,$v0 # move the resulting int to $t1

# print new line
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

#swap x and y values
move $s0,$t1 # move the resulting int to $s0
move $t1,$t0 # move the resulting int to $t1
move $t0,$s0 # move the resulting int to $t0

# print message before printing x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# print new swapped x value
li $v0,1 # code for print_int
move $a0,$t0 # put result in $a0
syscall # print out the result

# print space
li $v0,4 # code for print_string
la $a0,space # point $a0 to prompt string
syscall # print the prompt

# print message before printing y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# print new swapped y value
li $v0,1 # code for print_int
move $a0,$t1 # put result in $a0
syscall # print out the result

# print new line
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

# print programm end message
li $v0,4 # code for print_string
la $a0,end # point $a0 to end string
syscall # print end

# terminate program
li $v0,10 # code for exit
syscall # exit program


Code 2:

    For the second Code we will do the same but for 5 different sets of numbers. So, we will use Code 1 and put it inside of an for loop!

.data
# Constant strings to be output to the terminal
givex: .asciiz "x: "
givey: .asciiz "y: "
space: .asciiz " "
linefeed: .asciiz "\n"
end: .asciiz "End of Program!"

.text
main:
# initialize loop counter
li $s1,0

for:
# check condition
bge $s1,5,end_for

# print message for getting x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# get x as input
li $v0,5 # code for read_int
syscall #get int from user --> returned in $v0
move $t0,$v0 # move the resulting int to $t0

# print message for getting y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# get y as input
li $v0,5 # code for read_int
syscall # get int from user --> returned in $v0
move $t1,$v0 # move the resulting int to $t1

# print new line
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

#swap x and y values
move $s0,$t1 # move the resulting int to $s0
move $t1,$t0 # move the resulting int to $t1
move $t0,$s0 # move the resulting int to $t0

# print message before printing x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# print new swapped x value
li $v0,1 # code for print_int
move $a0,$t0 # put result in $a0
syscall # print out the result

# print space
li $v0,4 # code for print_string
la $a0,space # point $a0 to prompt string
syscall # print the prompt

# print message before printing y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# print new swapped y value
li $v0,1 # code for print_int
move $a0,$t1 # put result in $a0
syscall # print out the result

# print new line 2 times
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

# increment loop counter and jump
addi $s1,$s1,1 # s1++
j for
end_for:

# print programm end message
li $v0,4 # code for print_string
la $a0,end # point $a0 to end string
syscall # print end

# terminate program
li $v0,10 # code for exit
syscall # exit program


Code 3:

    Last Code for today will be running Code 1 infinitely ( while loop ), until x ( y after swapping ) is inputed as 0.

.data
# Constant strings to be output to the terminal
givex: .asciiz "x: "
givey: .asciiz "y: "
space: .asciiz " "
linefeed: .asciiz "\n"
end: .asciiz "End of Program!"

.text
main:
while:
# print message for getting x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# get x as input
li $v0,5 # code for read_int
syscall #get int from user --> returned in $v0
move $t0,$v0 # move the resulting int to $t0

# print message for getting y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# get y as input
li $v0,5 # code for read_int
syscall # get int from user --> returned in $v0
move $t1,$v0 # move the resulting int to $t1

# print new line
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

#swap x and y values
move $s0,$t1 # move the resulting int to $s0
move $t1,$t0 # move the resulting int to $t1
move $t0,$s0 # move the resulting int to $t0

# print message before printing x
li $v0,4 # code for print_string
la $a0,givex # point $a0 to prompt string
syscall # print the prompt

# print new swapped x value
li $v0,1 # code for print_int
move $a0,$t0 # put result in $a0
syscall # print out the result

# print space
li $v0,4 # code for print_string
la $a0,space # point $a0 to prompt string
syscall # print the prompt

# print message before printing y
li $v0,4 # code for print_string
la $a0,givey # point $a0 to prompt string
syscall # print the prompt

# print new swapped y value
li $v0,1 # code for print_int
move $a0,$t1 # put result in $a0
syscall # print out the result

# print new line 2 times
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed
li $v0,4 # code for print_string
la $a0,linefeed # point $a0 to linefeed string
syscall # print linefeed

# check if y == 0
beqz $t1,end_while 
j while 

end_while:
# print programm end message
li $v0,4 # code for print_string
la $a0,end # point $a0 to end string
syscall # print end

# terminate program
li $v0,10 # code for exit
syscall # exit program


This was the end of today's post! Next time we will get into Arrays and memory instructions! 

Hope you enjoyed it! Bye!

H2
H3
H4
3 columns
2 columns
1 column
2 Comments