In: Computer Science
Translate the following Code into MIPS (.asm)
Arrays and Reentrant Subprograms
CallingSubroutinesDemo.asm Implement the following pseudo code in a program called SubRoutinePractice.asm. Be sure to follow proper protocol for calling subroutines. Implement a prolog and epilog. // Main routine asks for three numbers from the user. Stores them in $s0, $s1 and $s2 // It then calls a subroutine that determines the largest and sum. // Program then prints the results main() { // $s0, $s1 and $s2 hold input values // $s3 and $s4 hold largest and average respectfully // Print(“Enter 2 values”); $s0 = readInt(); $s1 = readInt(); $s2 = readInt(); $a0 = $s0, $a1 = $s1, $a2 = $s2; $s3, $s4 = largestAndAverage($a0, $a1, $a2); // Print out “Largest is: “ + $s3 // Print out “The average is: “ + $s4 } // This subroutine receives three arguments. It calls getLarger to // find the largest and then calculates the average // It returns largest and average in $v0 and $v1 // Note: Since we are reusing $s0, $s1 and $s2, we MUST push those // registers onto the stack in the prolog and restore the values in the epilog // Don't forget the $ra!! Subprogram largestAndAverage($a0, $a1, $a2){ int $s0 = $a0, $s1 = $a1, $s2 = $a2; $s3 = getLarger($a0, $a1); // I need to move $s0 to $a0 and $s1 to $a1 $v0 = getLarger($a0, $a1); // Move $s3 to $a0 and $s2 to $a1 $v1 = ($s0 + $s1 + $s2) / 3; // Average is in $v1 return; } // This program does stuff. Subprogram getLarger($a0, $a1) { $v0 = $a0 if ($a1 > $a0) $v0 = $a1 return; }
# Demonstrate calling subroutines
# We walked through this code on 10/13 to help with the homework
assignments. Just a simple
# demonstration of calling subroutines.
.data
Prompt: .asciiz "This is an unused prompt"
.text
.globl main
main:
# Random numbers. Should get from user
li $s0, 4
li $s1, 5
li $s2, 6
# Want to call a subroutine. I need to move my variables in $s0,
$s1 and $s2 into
# the registers that are ALWAYS used to pass data to a
subroutine
move $a0, $s0 # Move my data to three by five cards and hand it to
him.
move $a1, $s1 # I don't want to give him my cards,
because he could mess them up.
move $a2, $s2
jal someStupidSubroutine
# when you get here, you can only be guaranteed that $s0, $s1 and
$s2 are the same
move $s3, $v0 # Because subroutines
ALWAYS return the results in $v0
move $a0, $s3
li $v0, 1
syscall
li $v0, 10
syscall
# ------------------------------------------------
# Each subroutine can have its own .data and .text
# We are simply telling the assembler what the code is used
for.
.data
s1Prompt: .asciiz "This is not used"
.text
someStupidSubroutine:
# Prolog - You have to do the following
# 1. You have to save any data that MUST be preserved on the
stack
# This includes the $ra register and any $s registers you are going
to use
# 2. To do that, you need to make room. Adjust the $sp
# 3. Push your data onto the stack
# Assume in "someStupidSubroutine" I am going to use $s0 and
$s1
# I need room for 3 words. $ra, $s0 and $s1
addi $sp, $sp, -12 # I just moved
the $sp down 12 bytes. So now I have room
# above the stack pointer to store information
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
# Logic
add $s0, $a0, $a1
add $s1, $s0, $a2 #
this is dumb but I'm doing it.
move $a0, $s0
# You have to move stuff around to ensure it is
in the right place
move $a1, $s1
jal someStupidSubroutine2
move $v0, $v0 # Move
results from someStupidSubroutine2 into $v0 (Not needed here,
but)
# if you had done other work
before the routine, you need to move the results)
# Epilog
# 1. Push your return value to $v0
# 2. Put the candle back. i.e. You need to put the information you
stored back where it was
lw $s1, 8($sp)
lw $s0, 4($sp)
lw $ra, 0($sp)
# I need to restore the return address
addi $sp, $sp, 12
jr $ra
# ---------------------------------------------------
.data
.text
someStupidSubroutine2:
# If this doesn't call any other subroutines or modify any $s
registers, it doesn't need
# an epilog and prolog
# Every subroutine definitely needs a .text. It will only need a
.data if it has static data
# Everything else is local and goes away when the subroutine does a
jr $ra
add $v0, $a0, $a1
jr $ra
Please find the answer below.
Please do comments in case of any issue. Also, don't forget to rate
the question. Thank You So Much.
# Demonstrate calling subroutines
# We walked through this code on 10/13 to help with the homework
assignments. Just a simple
# demonstration of calling subroutines..data
.data
prompt: .asciiz "Enter 3 values below\n"
prompt1: .asciiz "\nLargest is : "
prompt2: .asciiz "\nThe average is : "
.text
.globl main
main:
# Random numbers. Should get from user
li $s0, 4
li $s1, 5
li $s2, 6
li $v0,4
la $a0,prompt #it will print prompt
syscall
jal readInt
move $s0,$v0 #get s0
jal readInt
move $s1,$v0 #get s1
jal readInt
move $s2,$v0 #get s2
move $a0, $s0 # Move my data to three by five cards and hand it to
him.
move $a1, $s1 # I don't want to give him my cards, because he could
mess them up.
move $a2, $s2
jal largestAndAverage
li $v0,4
la $a0,prompt1 #it will print prompt
syscall
li $v0,1
move $a0,$s3
syscall
li $v0,4
la $a0,prompt2 #it will print prompt
syscall
li $v0,1
move $a0,$s4
syscall
li $v0, 10
syscall
largestAndAverage:
# Prolog - You have to do the following
# 1. You have to save any data that MUST be preserved on the
stack
# This includes the $ra register and any $s registers you are going
to use
# 2. To do that, you need to make room. Adjust the $sp
# 3. Push your data onto the stack
# Assume in "someStupidSubroutine" I am going to use $s0 and
$s1
# I need room for 3 words. $ra, $s0 and $s1
addi $sp, $sp, -12 # I just moved the $sp down 12 bytes. So now I
have room
# above the stack pointer to store information
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
sw $s2, 12($sp)
move $s3,$s0 #think may be s1 is greater
blt $s1,$s3,skip
move $s3,$s1 #think may be s1 is greater
skip:
blt $s2,$s3,skip2
move $s3,$s2 #think may be s1 is greater
skip2:
add $s4,$s0,$s1
add $s4,$s4,$s2 #get all sum
div $s4,$s4,3 #get average
lw $s2, 12($sp)
lw $s1, 8($sp)
lw $s0, 4($sp)
lw $ra, 0($sp) # I need to restore the return address
addi $sp, $sp, 12
jr $ra
readInt:
li $v0,5
syscall
jr $ra