Assignment 3
A Python program with functions and arrays
The following Python program builds a histogram for an array of data values between 0 and 99. It is spread across four different functions.
# returns the 10s digit of a two-digit number
def tens_digit(x):
return x // 10
# for each item in the data array, looks at its tens digit d
# and increment hist[d]
def build_hist(data, n, hist):
i = 0
while i < n:
d = tens_digit(data[i])
hist[d] = hist[d] + 1
i += 1
# prints the digit and a number of * equal to length argument
def print_bar(digit,length):
i = 0
print("\n",digit,"0s ",sep="",end="")
while i < length:
print("*", end="")
i += 1
print()
def main():
# how many data items we'll have
data_len = 50
# data we want to make into a histrogram by which digit is in the tens position
data = [0, 60, 23, 36, 5, 0, 43, 42, 48, 32, 0, 66, 65, 62, 28, 32, 53, 5, 98, 15, 47, 50, 24, 40, 0, 57, 43, 42, 25, 32, 48, 30, 40, 61, 8, 55, 16, 61, 0, 99, 91, 31, 81, 54, 47, 79, 39, 78, 44, 63]
# hist is an array for counting how many time we see each digit in the tens position
hist = [0,0,0,0,0,0,0,0,0,0]
build_hist(data, data_len, hist)
# print a bar for each digit
i = 0
while i < 10:
print_bar(i,hist[i])
i += 1
main()
Here’s the output you get when you run it in the console. Notice that it prints each tens digit and then a number of * characters reprenting how many of the data items had that tens digit.
00s ********
10s **
20s ****
30s *******
40s ***********
50s *****
60s *******
70s **
80s *
90s ***
A start to translating the Python program into MIPS
Here’s an attempt to translate the program into MIPS. The main, tens_digit, and print_bar procedures are finished, but you will need to finish implementing the build_hist procedure.
# =========================================
# Your Name:
#
# Histogram by tens digit, Python to MIPS translation
# of four functions: tens_digit, build_hist, print_bar, main
#
# =========================================
.data
# Input data (50 elements)
data: .word 0, 60, 23, 36, 5, 0, 43, 42, 48, 32,
0, 66, 65, 62, 28, 32, 53, 5, 98, 15,
47, 50, 24, 40, 0, 57, 43, 42, 25, 32,
48, 30, 40, 61, 8, 55, 16, 61, 0, 99,
91, 31, 81, 54, 47, 79, 39, 78, 44, 63
data_len: .word 50
# Histogram (10 zeros)
hist: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
# Strings / chars
newline: .asciiz "\n"
label_0s: .asciiz "0s "
star_char: .asciiz "*"
.text
########################
# main:
# - call build_hist(data, data_len, hist)
# - for each digit in 0..9 calls print_bar(digit, hist[digit])
########################
main:
# Build histogram
la $a0, data
lw $a1, data_len
la $a2, hist
jal build_hist
# Loop digit, i = 0..9
li $t0, 0 # i = 0
main_loop:
slti $t4, $t0, 10 # check i < 10
beq $t4, $zero, main_end # branch if the check fails
# a0 = i
move $a0, $t0
# a1 = hist[digit]
sll $t1, $t0, 2 # digit * 4
la $t2, hist # start of the hist array
add $t3, $t2, $t1 # calculating address of hist[digit]
lw $a1, 0($t3) # load value of hist[digit] into $a1
# call print_bar(digit, hist[digit])
jal print_bar
addi $t0, $t0, 1 #increment loop counter
b main_loop
main_end:
# Exit program
li $v0, 10
syscall
########################
# def tens_digit(x):
#return x // 10
#
# $a0: x - the two-digit value to find the tens digit of
#
########################
tens_digit:
li $t0, 10
div $a0, $t0 # results of division and multiplication end up in a special register called hi and lo
mflo $v0 # this instruction moves out of the lo register into another register, $v0 in this case
jr $ra # return
########################
# def build_hist(data, n, hist):
#i = 0
#while i < n:
#d = tens_digit(data[i])
#hist[d] = hist[d] + 1
#i += 1
#
# $a0: the address of the data array
# $a1: n - the number of items in the data array
# $a2: the address of the hist array
#
########################
build_hist:
# put your code here
# things to do
# - translate the code from the build_hist python function
# - make a call to the tens_digit function
# - for full credit, preserve needed registers by utilizing the stack
# - you must restore $ra and any $s_ registers to what they were originally before you return
# - you have to assume any $t_, $a_, or $v_ registers you need will be changed by functions you call
# - save them before making a call to tens_digit and restore them afterwards (using either $s_ registers or the stack)
jr $ra
########################
# def print_bar(digit,length):
#i = 0
#print("\n",digit,"0s ",sep="",end="")
#while i < length:
#print("*", end="")
#i += 1
#print()
#
# $a0: digit - digit to print before the bar
# $a1: length - the length of the bar to print
########################
print_bar:
move $s0, $a0 # save the digit we're working on
# print "\n"
li $v0, 4
la $a0, newline
syscall
# print the digit (as integer)
li $v0, 1
move $a0, $s0 # this is the digit we want to print
syscall
# print "0s "
li $v0, 4
la $a0, label_0s
syscall
# print '*' length times
li $t1, 0 # i = 0
pb_loop:
slt $t2, $t1, $a1 # check i < length
beq $t2, $zero, pb_done # branch out if i < length fails
# print a *
li $v0, 4
la $a0, star_char
syscall
addi $t1, $t1, 1 # increment loop counter
b pb_loop
pb_done:
# trailing newline
li $v0, 4
la $a0, newline
syscall
jr $ra # return
Assignment
Finish translating the build_hist function into a MIPS procedure.
The translation should do the following (in order of priority):
- allow the function to behave just the same way as the Python program
- call the
tens_digitprocedure from inside thebuild_histprocedure - inside
build_hist, use the stack (with$sp) to save$raand to make sure you restore any$s_registers that you use to their values that they had before the procedure started. Note that you should also expect thattens_digitcould change any of your$t_,$a_, or$v_registers, so preserver them before making the call by putting them on the stack or putting them in$s_registers.
Grading
This is an 8-point assignment. See the rubric from the syllabus, with the following exception:
The full 8 points will be for correct behavior with proper use of the stack and a call to tens_digit from within build_hist. You can get 7 points if it behaves correctly and you have utilized at least one of tens_digit and the stack. You can get 6 points for something that behaves correctly even if it uses neither of tens_digit nor the stack. You will get 5 points for significant progress towards the solution, even if it produces incorrect results.
What to turn in
Turn in the following items
- Your
.asmfile which contains your MIPS program - A
.txtfile (you can use Notepad, TextEdit, or even Visual Studio Code) where you paste in a sample run of your program that shows how it worked when you ran it in MARS
Where to turn it in
Submit your files to the Assignment 3 hand-in form on Blackboard.