Programming - Assembly Functions and Pseudodynamic Arrays

in #programming7 years ago (edited)

    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!

Sort:  

Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning.

- Albert Einstein

Coin Marketplace

STEEM 0.17
TRX 0.14
JST 0.028
BTC 58607.22
ETH 2616.94
USDT 1.00
SBD 2.43