Programming - Assembly Functions and Pseudodynamic Arrays

    Hello again, today I will talk about functions in Assembly and we will create a switch case menu that calls functions for each of the options. Afterwards, we will make the same code work for an pseudodynamic array (size < max). So, without further do, let's get started with how we use functions!


Functions:

    Functions in Assembly work the exact same way we used to use them in C. We will call them with specific parameters and afterwards get some return value(s). 

Things that are different in Assembly are: 

  • We have to insert the parameters/input inside of the $a registers and return_value/output inside of the $v registers.
  • The $s registers, as we already talked about in the first post, are callee saved and the $t are caller saved temporaries. So, we will not use any $s registers inside of a function, cause those values are being saved by the programm that called the function. So, a function contains only $t registers that are more than enough for the most functions. (it's not a must, but it's good to keep it that way)
  • An function gets called using the jal Label instruction. The functions work exactly like Labels and using the jal instruction we store the previous address from the main programm (or function) that called it inside of the $ra register and go back using the jr $ra instruction. When having more functions called, we will have to save those addresses inside of a stack (more in recursive functions tomorrow)


So, our code structure can now look like this:

.data
# variables, arrays, strings
.text
main:
# that contains termination somewhere
# and calls functions using jal
function1:
function2:
...
# that do something and return
# to main using jr


Simple example:

A simple function that checks if two values are the same looks like that:

check_same:
# $a0, $a1 are parameters
beq $a0, $a1, same #equality check
# not equal
li $v0, 0 # return value is 0
jr $ra
same:
li #v0, 1 # return value is 1
jr $ra


To call this function inside of the main function or another function we have to do the following:

li $a0, 5 # or move $a0, register
li $a1, 6 # or move $a1, register
jal check_same
# afterwards we can check the
# return value inside of $v0


Coding Section:

    Let's now get into coding to understand things even better. We will create a program that does the following:

  • Gets integers for an array as input
  • Prints a infinite loop switch case menu that looks like that:

          Give 0 to show the array

          Give 1 to find max

          Give 2 to find min

          Give 3 to exit

  • All (except exit) need to be called via functions        

Code 1:

    First we will make that work on an static array of size 6.

The Code looks like this:

.data
 Vector: .space 24
 # define strings
 menustring: .asciiz "Menu:\nGive 0 to show array.\nGive 1 to find max.\nGive 2 to find min.\nGive 3 to exit.\n"
 input: .asciiz "Please give 6 integers:\n"
 showarray: .asciiz "The array is:"
 maxelement: .asciiz "The max element is:"
 minelement: .asciiz "The min element is:"
 wrongchoice: .asciiz "Please give number from menu!\n"
 space: .asciiz " "
 newline: .asciiz "\n"
 end: .asciiz "Thank you and goodbye!"

# set main to global
.globl main
.text
main:
 # print message for getting integers
 li $v0,4
 la $a0,input
 syscall

 # loop to fill array
 li $s0,0
 for1:
 bge $s0,24,endfor1

 li $v0,5
 syscall
 move $s1,$v0
 sw $s1,Vector($s0)

 addi $s0,$s0,4
 j for1
 endfor1:

 # print menu until we receive 3
 menu:
 li $v0,4
 la $a0,menustring
 syscall

 # get input value
 li $v0,5
 syscall
 move $s0,$v0

 # cases
 beq $s0,0,case0
 beq $s0,1,case1
 beq $s0,2,case2
 beq $s0,3,endmenu
 
 # wrong choice
 li $v0,4
 la $a0,wrongchoice
 syscall
 j menu

 case0: #print array
 li $v0,4
 la $a0,showarray
 syscall
 
 # call show function
 li $a0, 6
 jal show

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 case1: #find max
 li $v0,4
 la $a0,maxelement
 syscall

 # call max function
 li $a0, 6
 jal max

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 case2: #find min
 li $v0,4
 la $a0,minelement
 syscall
 
 # call min function
 li $a0, 6
 jal min

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 endmenu: #end programm
 li $v0,4
 la $a0,end
 syscall
 
 li $v0,10
 syscall

show:
 # $a0 contains size of array
 mul $t1,$a0, 4 # array bytes
 
 # loop to show
 li $t0,0 # loop counter
 
 for2:
 # load from array
 lw $t2,Vector($t0)

 # print integer
 li $v0,1
 move $a0,$t2
 syscall

 # print space
 li $v0,4
 la $a0,space
 syscall

 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0,$t1,endfor2
 
 j for2
 endfor2:

 # return to main
 jr $ra

max:
 # $a0 contains size of array
 mul $t1, $a0, 4 # array bytes
 
 lw $t3,Vector($0) # first max
 li $t0,4 # loop counter
 
 for3:
 # load from array
 lw $t2,Vector($t0)
 
 # check if not max
 bgt $t3,$t2,notmax
 
 # make new max
 move $t3,$t2    
 
 notmax:
 
 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0, $t1, endfor3
 j for3
 endfor3:
 
 # print max
 li $v0,1
 move $a0,$t3
 syscall 

 # return to main
 jr $ra

min:
 # $a0 contains size of array
 mul $t1, $a0, 4 # array bytes
 
 lw $t3,Vector($0) # firstmin
 li $t0,4 # loop counter
 
 for4:
 # load from array
 lw $t2,Vector($t0)
 
 # check if not min
 blt $t3,$t2,notmin
 
 # make new min
 move $t3,$t2    
 
 notmin:
 
 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0,$t1,endfor4
 j for4
 endfor4:
 
 # print min
 li $v0,1
 move $a0,$t3
 syscall

 # return to main
 jr $ra


Code 2:

    In the second and last code we will have our array be pseudodynamic. The defined array will be for 15 Integers and we will get a value as input from the user that is <= to 15 so that it feels like we have an dynamic array (we will talk about dynamic ones some posts later on)

The Code looks like this:

.data
 Vector: .space 24
 # define strings
 menustring: .asciiz "Menu:\nGive 0 to show array.\nGive 1 to find max.\nGive 2 to find min.\nGive 3 to exit.\n"
 N: .asciiz "Please give N: "
 Nmax: .asciiz "N must be from 1 to 15!\n"
 input: .asciiz "Please give "
 input2: .asciiz " integers\n"
 showarray: .asciiz "The array is:"
 maxelement: .asciiz "The max element is:"
 minelement: .asciiz "The min element is:"
 wrongchoice: .asciiz "Please give number from menu!\n"
 space: .asciiz " "
 newline: .asciiz "\n"
 end: .asciiz "Thank you and goodbye!"

# set main to global
.globl main
.text
main:
 forN:   
 # print get N message
 li $v0,4
 la $a0,N
 syscall
 
 # get integer input
 li $v0,5
 syscall
 move $s3,$v0
 
 # use set instructions
 sle $s4,$s3,15
 sgt $s5,$s3,0
 and $s6,$s4,$s5,
 
 # check if its in between 0 and 15
 beq $s6,1,endforN
 
 # print <= 15 message
 li $v0,4
 la $a0,Nmax
 syscall
 j forN
 endforN:
 
 # print message for getting N integers
 li $v0,4
 la $a0,input
 syscall
 
 li $v0,1
 move $a0,$s3
 syscall
 
 li $v0,4
 la $a0,input2
 syscall

 # loop to fill array
 li $t0,0 # loop counter
 mul $t1,$s3,4 # last index in bytes
 
 for1:
 
 # get integer input
 li $v0,5
 syscall
 move $s0,$v0
 
 # write into array
 sw $s0,Vector($t0)

 # increment loop counter
 addi $t0,$t0,4
 
 # check condition
 bge $t0,$t1,endfor1
 j for1
 endfor1:

 # print menu until we receive 3
 menu:
 li $v0,4
 la $a0,menustring
 syscall

 # get input value
 li $v0,5
 syscall
 move $s0,$v0

 # cases
 beq $s0,0,case0
 beq $s0,1,case1
 beq $s0,2,case2
 beq $s0,3,endmenu
 
 # wrong choice
 li $v0,4
 la $a0,wrongchoice
 syscall
 j menu

 case0: #print array
 li $v0,4
 la $a0,showarray
 syscall
 
 # call show function
 add $a0, $s3, $0 # $s3 contains SIZE
 jal show

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 case1: #find max
 li $v0,4
 la $a0,maxelement
 syscall

 # call max function
 add $a0, $s3, $0 # $s3 contains SIZE
 jal max

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 case2: #find min
 li $v0,4
 la $a0,minelement
 syscall
 
 # call min function
 add $a0, $s3, $0 # $s3 contains SIZE
 jal min

 li $v0,4
 la $a0,newline
 syscall
 j menu
 
 endmenu: #end programm
 li $v0,4
 la $a0,end
 syscall
 
 li $v0,10
 syscall

show:
 # $a0 contains size of array
 mul $t1,$a0, 4 # array bytes
 
 # loop to show
 li $t0,0 # loop counter
 
 for2:
 # load from array
 lw $t2,Vector($t0)

 # print integer
 li $v0,1
 move $a0,$t2
 syscall

 # print space
 li $v0,4
 la $a0,space
 syscall

 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0,$t1,endfor2
 
 j for2
 endfor2:

 # return to main
 jr $ra

max:
 # $a0 contains size of array
 mul $t1, $a0, 4 # array bytes
 
 lw $t3,Vector($0) # first max
 li $t0,4 # loop counter
 
 for3:
 # load from array
 lw $t2,Vector($t0)
 
 # check if not max
 bgt $t3,$t2,notmax
 
 # make new max
 move $t3,$t2    
 
 notmax:
 
 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0, $t1, endfor3
 j for3
 endfor3:
 
 # print max
 li $v0,1
 move $a0,$t3
 syscall 

 # return to main
 jr $ra

min:
 # $a0 contains size of array
 mul $t1, $a0, 4 # array bytes
 
 lw $t3,Vector($0) # firstmin
 li $t0,4 # loop counter
 
 for4:
 # load from array
 lw $t2,Vector($t0)
 
 # check if not min
 blt $t3,$t2,notmin
 
 # make new min
 move $t3,$t2    
 
 notmin:
 
 # increment loop counter
 addi $t0,$t0,4
 
 # check loop condition
 bge $t0,$t1,endfor4
 j for4
 endfor4:
 
 # print min
 li $v0,1
 move $a0,$t3
 syscall

 # return to main
 jr $ra


This is the end of today's post. Hope you enjoyed it!

Next time (tomorrow) we will get into recursive functions and how we store the $ra address inside of a stack to call a function inside of a function and so on...

Until next time, Bye!

H2
H3
H4
3 columns
2 columns
1 column
1 Comment