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!
Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning.
- Albert Einstein