Lab 10 Floatingpoint Name Date Description ask the
###########################################################
# Lab 10 - Floating-point
#
# Name:
# Date:
#
# Description:
# ask the user for an array length, and then allocate a dynamic array of
# double-precision floating-point values (each array element is 8 bytes) of the given length
# Then, store the base address and length of the array in static memory
#
# call read_double_array to fill the array
# call print_double_array to print the array contents
# call get_sum_avg to get the sum and average
# print the sum and average
#
# ask the user for a maximum value
# call print_less_than to print all values less than the given maximum
#
# High level design:
# from main: ask for array length
# from main: allocate dynamic array of double-precision
# from main: store array length and array base address in static variable
#
# from main call: null <-- subprogram read_double_array(array base address, array length)
# from main call: null <-- print_double_array(array base address, array length)
# from main call: sum and average <-- get_sum_avg(array base address, array length)
#
# from main: ask the user for a maximum value
# from main call: null <-- print_less_than(array base address, array length, partition value)
#
###########################################################
# Register Usage
# $t0 Holds array base address (temporarily)
# $t1 Holds array length (temporarily)
# $t2
# $t3
# $t4
# $t5
# $t6
# $t7
# $t8
# $t9 temporary register
# $f4|$f5 Holds array sum (double-precision floating-point)
# $f6|$f7 Holds array average (double precision floating-point)
###########################################################
.data
array_size_prompt_p: .asciiz \"Enter an array size: \"
sum_p: .asciiz \"Array sum is: \"
average_p: .asciiz \"Array average is: \"
partition_p: .asciiz \"Enter a partition value: \"
nextline_p: .asciiz \"\ \" # \
# declare words to hold dynamic array base and array length
array_pointer_p: .word 0 # holds address dynamic array pointer (address)
array_size_p: .word 0 # hold size of dynamic array (value)
###########################################################
.text
main:
mainEnd:
li $v0, 10
syscall # Halt
###########################################################
# read_double_array subprogram
#
# Subprogram description:
# Reads double-precision floating-point numbers into an array,
# printing a prompt before reading each double
#
###########################################################
# Arguments IN and OUT of subprogram
# $sp+0 Holds array base address (IN)
# $sp+4 Holds array length (IN)
###########################################################
# Register Usage
# $t0 Holds array index address
# $t1 Holds array length/loop countdown
# $f0|$f1 Holds array entry
###########################################################
.data
read_double_array_prompt_p: .asciiz \"Enter a real number: \"
###########################################################
.text
read_double_array:
read_double_array_end:
jr $ra # jump back to the main
###########################################################
# print_double_array subprogram
#
# Subprogram description:
# Print array of double-precision floating-point numbers
#
###########################################################
# Arguments IN and OUT of subprogram
# $sp+0 Holds array base address (IN)
# $sp+4 Holds array length (IN)
###########################################################
# Register Usage
# $t0 Holds array index address
# $t1 Holds array length/loop countdown
# $f12|$f13 Holds array value
###########################################################
.data
print_double_array_prompt_p: .asciiz \"Array: \"
print_double_array_space_p: .asciiz \" \"
###########################################################
.text
print_double_array:
print_double_array_end:
jr $ra # jump back to the main
###########################################################
# get_sum_avg subprogram
#
# Subprogram description:
# Calculate sum and average of an array of doubles
# If the number of elements is 0, print an error and return 0.0 for both sum and average
#
# Remember, to calculate average we need to divide sum (:: double) / (:: integer)
# But there is no type promotion (or widening primitive conversion)in MIPS, which mean as a programmer we have to
# implicitly convert count to double before being able to sum by count.
#
###########################################################
# Arguments IN and OUT of subprogram
# $sp+0 Holds array base address (IN)
# $sp+4 Holds array length (IN)
# $sp+8 Holds array sum {double precision floating-point number} (OUT)
# $sp+16 Holds array average {double precision floating-point number} (OUT)
###########################################################
# Register Usage
# $t0 Holds array index address
# $t1 Holds array length/loop countdown
# $t2 Holds loop countdown
# $f4|$f5 Holds array Sum
# $f6|$f7 Holds array Average
# $f8|$f9 Holds array value/Count
###########################################################
.data
get_sum_avg_invalid_count_p: .asciiz \"Invalid count, cannot calculate average\ \"
###########################################################
.text
get_sum_avg:
get_sum_avg_end:
jr $ra # jump back to the main
###########################################################
# print_less_than subprogram
#
# Subprogram description:
# Prints all values from the array which are less
# than the given maximum
#
###########################################################
# Arguments IN and OUT of subprogram
# $sp+0 Holds array base address (IN)
# $sp+4 Holds array length (IN)
# $sp+8 Holds maximum value {double precision floating-point number} (IN)
###########################################################
# Register Usage
# $t0 Holds array index address
# $t1 Holds array length/Loop countdown
# $f4|$f5 Holds partition value
# $f12|$f13 Holds array value (array element at any particular index)
###########################################################
.data
print_less_than_prompt_p: .asciiz \"Array values less than partition value are: \"
print_less_than_space_p: .asciiz \" \"
###########################################################
.text
print_less_than:
print_less_than_end:
jr $ra # jump back to the main
###########################################################
Solution
.data
str1:.asciiz \"Enter length of array\"
arr: .space 40 #10 element integer array
.text
la $a0,str1 #Load and print string asking for string
li $v0,4
syscall
main:
li $v0,8 #take in input
la $a0, buffer #load byte space into address
li $a1, 20 # allot the byte space for string
move $t0,$a0 #save string to t0
li $v1, 9 # Load system instruction to allocate dynamic memory
li $t1, 8 # 8 bytes per element
mult $t0, $t1 # Calculates how big the allocated memory has to be in bytes.
mflo $a0 # Loads this value into $a0
syscall # Allocates memory and returns address into $v0
la $s0, arr # load address of arr into $s0
sw $v1, ($s0) # Save allocated memory address into the space reserved in .text
jal : read_double_array
jal : print_double_array
jal : get_sum_avg
jal : print_less_than
mainEnd:
read_double_array
li $v0, 10
syscall # Halt
.text
str2: .asciiz \"Enter element\"
read_double_array:
.data
prompt: .asciiz \"Input Row \"
colon: .asciiz \": \"
Output: .asciiz \"\ Output Row \"
space: .asciiz \" \"
newline: .asciiz \"\ \"
array: .space 33
char: .space 2
.text
main:
li $t9, 1 # counter for prompt
la $s1, array #set base address of array to s1
# main loop at beginning of the program that prompts for Input row 4 times, each time continuing to take input until a newline character is found
prompt_loop:
beq $t9, 5, finished_input # ends this when we are about to start the 5th iteration
la $a0, prompt #load prompt message into $a0
li $v0, 4 # printstring
syscall
la $a0, ($t9) #load prompt message into $a0 for syscall
li $v0, 1 # printstring
syscall
la $a0, colon # load colon into $a0
li $v0, 4 # printstring
syscall
# read loop deels with newline and spaces by giving control flow away to other places, adapted from Stack Overflow answer about processing strings
# to integers
read_loop: #start of read loop
jal getc #jump to getc subroutine
#storing char into array
lb $t0, char #load the char from char buffer into t0, stripping space
sb $t0, 0($s1) #store the char into the nth elem of array
#checking for end of line
lb $t1, newline #load newline char into t1
beq $t0, $t1, prompt_counter_increase #end of string? jump to finished_looping
#checking for space
lb $t1, space #load newline char into t1
beq $t0, $t1, read_loop # keeps going as though nothing has happened if we run across a space
addi $s1, $s1, 1 # increments base address of array j loop #jump to start of read loop
# get character subroutine found on Stack Overflow and slightly modified
getc: #read char from keyboard buffer and return ascii value
li $v0, 8 # read string
la $a0, char #load address of char
li $a1, 2 # length of string is 1byte char and 1byte for space, defined above already
syscall # store the char byte from input buffer into char
jr $ra #jump-register to calling function, which is back to read_loop
# increments counter after successfully encountering a newline char
prompt_counter_increase:
addi $t9, $t9, 1 # increment counter
j prompt_loop # jumps back to prompt_loop because we need next line
# resets the counter so elements can be spit back out the same order and also loads the array again, pretty much just reset everything
finished_input:
addi $t9, $t9, -4 # resets the counter because the way we have it set up we increment it again to echo everything in the right order
la $s1, array # loads the array back into $s1
# this pretty much does what prompt_loop did but in reverse
output_loop:
beq $t9, 5, end_program # same concept, we have reset $t9 earlier in finished_input
la $a0, Output #load output prompt to $a0
li $v0, 4 # print string
syscall
la $a0, ($t9) # load prompt message into $a0 for syscall
li $v0, 1 # print int
la $a0, colon #load prompt message into $a0
li $v0, 4 # print string
syscall
li $t3, 1 # this counter is used
# turns ascii to int, this method takes our array and reformats it into how it looked when it was input, ie we add spaces
string_to_integer:
beq $t3, 5, output_counter_increase
addi $t3,$t3,1 # increment counter
lb $a0,($s1) # load byte of the first char
lb $t1, newline #load newline char into t1
beq $a0, $t1, end_program #end of string? jump to finished_looping
addi $a0, $a0,-48 # turns ascii to int
li $v0, 1 # print int
syscall
la $a0, space # load prompt message into $a0 for syscall
li $v0, 4 #load syscall to print string
syscall
addi $s1, $s1, 1 #increments base address of array
j string_to_integer # loops back itself
#increments output counter
output_counter_increase:
addi $t9, $t9, 1 #increment
j output_loop # back to the loop again
#ends the program
end_program:
li $v0, 10 #exits
syscall
read_double_array_end:
jr $ra # jump back to the main
.text
print_double_array:
print_double_array_end:
jr $ra # jump back to the main
.text
get_sum_avg:
get_sum_avg_end:
jr $ra # jump back to the main
.text
print_less_than:
print_less_than_end:
jr $ra # jump back to the main








