MIPS - implementing a binary search tree - mips
As our term project, we're implementing a binary search tree. The thought behind it is as follows:
Assume a bst with 3 nodes:
10
/ \
/ \
8 14
Its address representation is as follows (value, left node address, right node address, root node address)t:
400:|----------|
| 8 |
|----------|
| 0 |
|----------|
| 0 |
|----------|
| 620 |
|----------|
| . |
| . |
| . |
$a0=620:|----------|
| 10 |
|----------|
| 400 |
|----------|
| 1000 |
|----------|
| 0 |
|----------|
| . |
| . |
| . |
1000:|----------|
| 14 |
|----------|
| 0 |
|----------|
| 0 |
|----------|
| 620 |
|----------|
So, according to these information, how can I struct a bst in mips assembly? Integers are 4-bytes yes, but the other ones are addresses, so they need 4-bytes since mips addresses are 32 bits. So does every node worth 4+4+4+4=16 bytes?
I had a similar project.
My solution was as follows:
##################################################
#
# Binary Search Tree - Project 1
#
# First Assembly Program :)
#
##################################################
.data
nl: .asciiz "\n"
prompt1: "\nPlease select an option from the list below:\n"
prompt2: "[A] - Add a record to the tree\n"
prompt3: "[F] - Find a record in the tree\n"
prompt4: "[P] - Perform a preorder traversal\n"
prompt5: "[I] - Perform an inorder traversal\n"
prompt6: "[Q] - Quit the program\n"
prompt7: "\nChoose a character: "
empty: "\nThe Tree is Empty."
youentered: "\nYou Entered: "
recordfound: "\nRecord Found: "
recordnotfound: "\nRecord Not Found! "
goodbye: "\nGoodbye!"
addid: "\nEnter the ID to add: "
addyear: "Enter the year: "
addtitle: "Enter the title: "
adddescription: "Enter the description: "
id: "\nID: "
year: "\nYear: "
title: "\nTitle: "
description: "Description: "
#idsize: .word 0
#optiona: 97 addrecord a
#optionf: 102 findrecord f
#optionp: 112 preorder p
#optioni: 105 inorder i
#optionq: 113 quit q
###################################################################
#
# Note: I reuse a lot of print statements
# This code is far from what I would call optimized
#
# This is my first assembly program and I'm really just
# Happy to see it all working :)
#
# I spent about 18 hours writing this so lol :)
#
# The only thing that I've gotten to crash it so far is
# Entering characters when it's waiting for an int :)
#
######################################################
#
# Here is my memory setup:
#
# $s5 - Stores Root Node
# $s7 - Stores Size of Tree (Not Really Necessary)
#
# Each New Item Contains a chunk of 344 bytes
# The bytes are setup as such:
#
# 8 Bytes - [ID]
# 8 Bytes - [Year]
# 64 Bytes - [Title]
# 256 Bytes - [Description]
# 8 Bytes - [LeftNodeAddress]
# 8 Bytes - [RightNodeAddress]
#
#
# Example Tree:
#
# 10 -Root
# / \
# 7 15 -Branch
# / \ / \
# 6 9 12 17 -Leaf
#
# In Memory:
#
# [Offset: 328] - [ID] - [Offset: 336]
# | |
# [Off: 328][ID][Off:336] [Off: 328][ID][Off: 336] . . .
#
#
########################################################
.text
###################
##Prompt Function##
###################
prompt:
li $v0, 4
la $a0, prompt1 #Please select an option from the list below:
syscall
li $v0, 4
la $a0, prompt2 #[A] - Add a record to the tree
syscall
li $v0, 4
la $a0, prompt3 #[F] - Find a record in the tree
syscall
li $v0, 4
la $a0, prompt4 #[P] - Preorder traversal
syscall
li $v0, 4
la $a0, prompt5 #[I] - Inorder traversal
syscall
li $v0, 4
la $a0, prompt6 #[Q] - Quit the program
syscall
###################
##Get User Input ##
###################
getinput:
li $v0, 4 #Choose a character:
la $a0, prompt7
syscall
li $v0, 12 #Read a single character from console
syscall
move $s0, $v0
beq $s0, 97, addrecord #If you press 'a', addrecord
beq $s0, 102, findrecord #If you press 'f', findrecord
beq $s0, 112, preorder #If you press 'p', preorder
beq $s0, 105, inorder #If you press 'i', inorder
beq $s0, 113, exit #If you press 'q', exit
li $v0, 4 #If you press something random
la $a0, nl #Display new line
syscall
j getinput #And ask for a new character
###################
## Add A Record ##
###################
addrecord:
li $v0, 9 #allocate memory for new record
li $a0, 344 #enough memory for 2 addresses and all the data
syscall
move $s0, $v0 #hang onto the initial address of all our info
li $v0, 4 #prompt for ID
la $a0, addid
syscall
li $v0, 5 #enter integer
syscall
sw $v0, 0($s0) #store our ID into memory Offset: 0
li $v0, 4 #prompt for add year
la $a0, addyear
syscall
li $v0, 5 #enter integer
syscall
sw $v0, 4($s0) #store year into our memory Offset: 4
li $v0, 4 #prompt for add title
la $a0, addtitle
syscall
li $v0, 8 #read our title into the allocated space
la $a0, 8($s0) #Offset: 8
li $a1, 64
syscall
li $v0, 4 #prompt for add description
la $a0, adddescription
syscall
li $v0, 8 #read our description into the allocated space
la $a0, 72($s0) #Offset: 72
li $a1, 256
syscall
bne $s7, 0, setlocations #if this isn't root node let's set the locations
add $s7, $s7, 1 #add 1 to the size of the records
move $s5, $s0 #store this address as root node for now
j prompt
########################
##Set Memory Locations##
########################
setlocations:
move $s6, $s5 #Keep $s5 as our root and use $s6 as temporary storage
move $s4, $s6 #Use $s4 to find the null node slot
storelocations:
beqz $s4, store #If we've reached a leaf, store
lw $t2, 0($s4) #get ID from current node
lw $t1, 0($s0) #get Current ID from new node node we're adding
ble $t1,$t2,goleft #get left location if new node <= current node
move $s6, $s4
lw $s4, 336($s4) #get node to the right if new node > current node
li $t3, 336 #be ready to store to the right slot
j storelocations
goleft:
move $s6, $s4
lw $s4, 328($s4) #load the node to the left
li $t3, 328 #be ready to store to the left slot
j storelocations
store:
beq $t3, 336, storeright #if $t3 was set to storeRight, then store to the right
sw $s0, 328($s6) #else store the new node's location into our node's left slot
add $s7, $s7, 1 #remind our size register that it's growing
j prompt #back to the prompt
storeright:
sw $s0, 336($s6) #store new node to the right slot
add $s7, $s7, 1 #remind our size register that it's growing
j prompt #back to the prompt
########################
## Find Record by ID ##
########################
findrecord:
move $s6, $s5
bne $s7, 0, search
li $v0, 4 #if tree is empty
la $a0, empty #display message Tree is empty
syscall
j prompt #and go wait for input
search:
move $s6, $s5
li $v0, 4 #print ID:
la $a0, id
syscall
li $v0, 5 #let user enter ID
syscall
move $t1, $v0 #store the id we're looking for in $t1
checkagain:
lw $t2, ($s6) #store the id we're currently looking at
bne $t1, $t2, checkempty #if this isn't the right ID, is it the last one?
###########################
##If we find the record:
###########################
li $v0, 4
la $a0, recordfound #Record Found:
syscall
li $v0, 4 #Print ID:
la $a0, id
syscall
li $v0, 1 #Print the ID stored at $s6 [Offset: 0]
lw $a0, 0($s6)
syscall
li $v0, 4 #Print Year:
la $a0, year
syscall
li $v0, 1 #Print the Year stored at $s6 [Offset: 4]
lw $a0, 4($s6)
syscall
li $v0, 4 #Print Title:
la $a0, title
syscall
li $v0, 4 #Print the Title stored at $s6 [Offset: 8]
la $a0, 8($s6)
syscall
li $v0, 4 #Print Description:
la $a0, description
syscall
li $v0, 4 #Print descript stored at $s6 [Offset: 72]
la $a0, 72($s6)
syscall
j getinput
checkempty:
ble $t1, $t2, checkleft #If $t1 <= $t2 check the left node
lw $s6, 336($s6) #Otherwise check the right node
bne $s6, 0, checkagain #If this record isn't empty, check again
li $v0, 4 #Otherwise
la $a0, recordnotfound #Record not found
syscall
j getinput
checkleft:
lw $s6, 328($s6) #Check the left node
bne $s6, 0, checkagain #If the record isn't empty, check again
li $v0, 4 #Otherwise
la $a0, recordnotfound #Record not found
syscall
j getinput
treeempty:
li $v0, 4 #if tree is empty
la $a0, empty #display message Tree is empty
syscall
j prompt
#####################################
#
# The Inorder Function
#
#####################################
inorder:
beq $s7, 0, treeempty #If the tree is empty display empty message
move $s6, $s5 #$s6 is the record we're currently at
move $t0, $s6 #t0 will iterate $s6 is our starting node
move $t1, $t0 #t1 will be thrown on the stack to keep track of everything
jal printinorder
j prompt
printinorder:
addi $sp, $sp, -12 #allocate 12 bytes for the stack
sw $ra, 0($sp) #4 for the $ra variable
sw $t1, 4($sp) #4 for $t1
bne $t0, 0, dontreturn #if $t0 isn't null don't return
lw $ra, 0($sp) #otherwise:
lw $t1, 4($sp) #pop stack
addi $sp, $sp, 12 #and prepare
jr $ra #to return
dontreturn:
move $t1, $t0 #put $t0 in $t1
lw $t0, 328($t0) #load the next pointer to the left
jal printinorder #and recurse back to printorder
move $s6, $t1 #if we're back here, it's time to print
j goprint #so go print
afterprint:
move $t0, $t1 #after we print, move $t1 back to $t0
lw $t0, 336($t0) #get the next pointer to the right
jal printinorder #recurse to see if it's the last one
move $s6, $t1 #if we made it here, it is, let's print
beq $s6, $t1, done #if we already printed this one, we're done (Root Node)
j goprint #Go print the node to the right
done:
lw $ra, 0($sp) #if we're done, pop our stack
lw $t1, 4($sp) #clean it up
addi $sp, $sp, 12 #12 bytes worth
jr $ra #and return
goprint:
li $v0, 4 #Print ID:
la $a0, id
syscall
li $v0, 1 #Print the ID stored at $s6 [Offset: 0]
lw $a0, 0($s6)
syscall
li $v0, 4 #Print Year:
la $a0, year
syscall
li $v0, 1 #Print the Year stored at $s6 [Offset: 4]
lw $a0, 4($s6)
syscall
li $v0, 4 #Print Title:
la $a0, title
syscall
li $v0, 4 #Print the Title stored at $s6 [Offset: 8]
la $a0, 8($s6)
syscall
li $v0, 4 #Print Description:
la $a0, description
syscall
li $v0, 4 #Print descript stored at $s6 [Offset: 72]
la $a0, 72($s6)
syscall
j afterprint
#####################################
#
# The Preorder Function
#
#####################################
preorder:
beq $s7, 0, treeempty #If the tree is empty display empty message
move $s6, $s5 #$s6 is the record we're currently at
move $t0, $s6 #t0 will iterate $s6 is our starting node
move $t1, $t0 #t1 will be thrown on the stack to keep track of everything
jal printpreorder
j prompt
printpreorder:
addi $sp, $sp, -12 #allocate 12 bytes for the stack
sw $ra, 0($sp) #4 for the $ra variable
sw $t1, 4($sp) #4 for $t1
bne $t0, 0, dontreturnpo #if $t0 isn't null don't return
lw $ra, 0($sp) #otherwise:
lw $t1, 4($sp) #pop stack
addi $sp, $sp, 12 #and prepare
jr $ra #to return
dontreturnpo:
move $s6, $t0 #if we made it here, it is, let's print
j goprintpo #so go print
afterprintpo:
move $t1, $t0 #put $t0 in $t1
lw $t0, 328($t0) #load the next pointer to the left
jal printpreorder #and recurse back to printorder
move $t0, $t1 #after we print, move $t1 back to $t0
lw $t0, 336($t0) #get the next pointer to the right
jal printpreorder #recurse to see if it's the last one
donepo:
lw $ra, 0($sp) #if we're done, pop our stack
lw $t1, 4($sp) #clean it up
addi $sp, $sp, 12 #12 bytes worth
jr $ra #and return
goprintpo:
li $v0, 4 #Print ID:
la $a0, id
syscall
li $v0, 1 #Print the ID stored at $s6 [Offset: 0]
lw $a0, 0($s6)
syscall
li $v0, 4 #Print Year:
la $a0, year
syscall
li $v0, 1 #Print the Year stored at $s6 [Offset: 4]
lw $a0, 4($s6)
syscall
li $v0, 4 #Print Title:
la $a0, title
syscall
li $v0, 4 #Print the Title stored at $s6 [Offset: 8]
la $a0, 8($s6)
syscall
li $v0, 4 #Print Description:
la $a0, description
syscall
li $v0, 4 #Print descript stored at $s6 [Offset: 72]
la $a0, 72($s6)
syscall
j afterprintpo
exit:
li $v0, 4 #Say
la $a0, goodbye #Goodbye!
syscall
li $v0, 10 #Terminate Program
syscall
Related
Why is error exception 7 occuring in my MIPS Code
I'm writing code for my assembly language course and I'm coming across this error although it's still producing the correct output. "Exception 7 [Bad Data Address]" "Exception occurred at PC=0x00400084" # MIPS Code for Counting Vowels in a given string Using procedure #***************************************************************** .data str: .asciiz "The Spirit is willing, but the flesh is weak - The Vodka was good, but the Meat was rotten - Out of Sight, out of mind - Invisible insanity, blind and insane" p1: .asciiz "Given String: " Ans: .asciiz "\n\nNo. of vowels = " #***************************************************************** .text .globl main main: # Print p1 and str li $v0, 4 la $a0, p1 syscall li $v0, 4 la $a0, str syscall # Print Ans li $v0, 4 la $a0, Ans syscall # Prepping Procedure la $a0, str # Load str into a0 for procedure (not necessary in this case but usually is) jal VCount # Jump and link to procedure move $a0, $v0 # Moving the No. of vowels into a0 li $v0, 1 # Print the integer syscall # Procedure VCount: li $s1, 0 li $s0, 0 addi $sp, $sp, -16 # Creating the stack and giving 16 depth sw $s0, 0($sp) # Storing registers into stack sw $s1, 4($sp) sw $a0, 8($sp) sw $ra, 12($sp) move $s1, $a0 # Moving string into s1 Loop: lb $a0, 0($s1) # Loading first byte of string in s1 into a0 beqz $a0, End # a0 = 0 then end loop jal CheckV # Jump and link to CheckV procedure add $s0, $s0, $v0 # Counter for vowels addi $s1, $s1, 1 # Navigating through the string 1 letter at a time j Loop # After loop End: move $v0, $s0 lw $s0, 0($sp) # Loading registers from stack lw $s1, 4($sp) lw $a0, 8($sp) lw $ra, 12($sp) addi $sp, $sp, 16 # Countering the -16 stack jr $ra # Transfer control # Checking Vowels CheckV: li $v0, 0 beq $a0, 'a', Yes # Checks for a0 being a vowels and jumps to Yes to increase count of vowels beq $a0, 'e', Yes beq $a0, 'i', Yes beq $a0, 'o', Yes beq $a0, 'u', Yes beq $a0, 'A', Yes # Capital vowels beq $a0, 'E', Yes beq $a0, 'I', Yes beq $a0, 'O', Yes beq $a0, 'U', Yes jr $ra # Transfer control if no vowels Yes: li $v0, 1 # Increase No. of vowels jr $ra # Transfer control # Exit li $v0, 10 syscall
How do I continue my program after the "##"
So I have made a program which allows users to put how many hello world that they want and after ## there is another function but that won't play out instead the program just closes. .data n: .space 4 msg: .asciiz "Hello World" prom1: .asciiz "How many Hello World want to be printed: " mychar1:.byte 'a' out_string: .asciiz "\nHello World\n" prom: .asciiz "Type a number: " mychar: .byte 'm' res: .asciiz "Result is: " nl: .asciiz "\n" .text main: li $v0, 4 la $a0, msg syscall li $v0, 4 # print str la $a0, nl # at nl syscall li $v0, 4 # print str la $a0, nl # at nl syscall li $v0, 4 la $a0, prom1 # Load address of first prompt syscall li $v0, 5 # Read int from user syscall li $t1, 0 # Load 0 into $t1 for comparison move $t0, $v0 # Move the user input to $t0 loop: beq $t1, $t0, end # Break If Equal: branch to 'end' when $t1 == $t2 li $v0, 4 la $a0, out_string # Load address of output string syscall add $t1, $t1, 1 # Increment $t1 j loop # Jump back up to loop end: li $v0, 10 # Load syscall 10 to indicate end of program syscall ## li $v0, 4 # print str la $a0, nl # at nl syscall li $v0, 4 # print str la $a0, prom # at prom syscall li $v0, 5 # read int syscall sw $v0, n # store in n li $v0, 4 # print str la $a0, res # at res syscall li $v0, 1 # print int lw $t0, n # n sub $t1, $t0, 1 # n-1 mul $t0, $t0, $t1 # * sra $a0, $t0, 1 # /2 syscall li $v0, 4 # print str la $a0, nl # at nl syscall li $v0, 4 # print str la $a0, nl # at nl syscall li $v0, 10 # exit syscall
In this spot here end: li $v0, 10 # Load syscall 10 to indicate end of program syscall You are calling a syscall with 10 in the $v0 register. This tells the computer to stop the program. So in this case you are just stopping the program before the rest of the code is executed. Instead you could do this loop: beq $t1, $t0, endloop li $v0, 4 la $a0, out_string # Load address of output string syscall add $t1, $t1, 1 # Increment $t1 j loop # Jump back up to loop endloop: # Put rest of code here This is just the way to end the loop and continue. Then at the end of the program you can put the syscall 10
I keep getting 0 as an answer for my mips code where I'm supposed to find the gcd of two numbers
.data n1:.asciiz"Enter the first number:" n2: .asciiz"Enter the second number:" .text .globl main main: li $v0,4 la $a0,n1 syscall li $v0, 5 # get input from user syscall move $a0,$s0 li $v0,4 la $a0,n2 syscall li $v0, 5 # get second input from user syscall move $a0,$s1 jal calcGCD # call function calcGCD add $a0,$v0,$zero li $v0,1 syscall # print result li $v0, 10 # exit program syscall calcGCD: #GCD(n1, n2) # n1 = $a0 # n2 = $a1 addi $sp, $sp, -12 sw $ra, 0($sp) # save function into stack sw $s0, 4($sp) # save value $s0 into stack sw $s1, 8($sp) # save value $s1 into stack add $s0, $a0, $zero # s0 = a0 ( value n1 ) add $s1, $a1, $zero # s1 = a1 ( value n2 ) addi $t1, $zero, 0 # $t1 = 0 beq $s1, $t1, return # if s1 == 0 return add $a0, $zero, $s1 # make a0 = $s1 div $s0, $s1 # n1/n2 mfhi $a1 # reminder of n1/n2 which is equal to n1%n2 jal calcGCD exitGCD: lw $ra, 0 ($sp) # read registers from stack lw $s0, 4 ($sp) lw $s1, 8 ($sp) addi $sp,$sp , 12 # bring back stack pointer jr $ra return: add $v0, $zero, $s0 # return $v0 = $s0 ( n1) j exitGCD
The main issue with your code is with the part where you store the user input in the registers. In move $a0,$s0, you are moving the value at $s0 into $a0 when the user input is stored in $v0, therefore, it should be move $a0,$v0, and from your function, you seem to have stored the second input in $a1 but in your code, both the inputs are being stored in the same register so the next command should be move $a1,$v0. Here is one version of your code. .data n1:.asciiz"Enter the first number:" n2: .asciiz"Enter the second number:" .text .globl main main: li $v0,4 la $a0,n1 syscall li $v0, 5 # get input from user syscall move $t0,$v0 #temporarily store the user input in another register because $a0 is having another value stored in it in the next command li $v0,4 la $a0,n2 syscall li $v0, 5 # get second input from user syscall move $a1,$v0 move $a0,$t0 #transfer the first user input into $a0 to be used in the function jal calcGCD # call function calcGCD add $a0,$v0,$zero li $v0,1 syscall # print result li $v0, 10 # exit program syscall calcGCD: #GCD(n1, n2) # n1 = $a0 # n2 = $a1 addi $sp, $sp, -12 sw $ra, 0($sp) # save function into stack sw $s0, 4($sp) # save value $s0 into stack sw $s1, 8($sp) # save value $s1 into stack add $s0, $a0, $zero # s0 = a0 ( value n1 ) add $s1, $a1, $zero # s1 = a1 ( value n2 ) addi $t1, $zero, 0 # $t1 = 0 beq $s1, $t1, return # if s1 == 0 return add $a0, $zero, $s1 # make a0 = $s1 div $s0, $s1 # n1/n2 mfhi $a1 # reminder of n1/n2 which is equal to n1%n2 jal calcGCD exitGCD: lw $ra, 0 ($sp) # read registers from stack lw $s0, 4 ($sp) lw $s1, 8 ($sp) addi $sp,$sp , 12 # bring back stack pointer jr $ra return: add $v0, $zero, $s0 # return $v0 = $s0 ( n1) j exitGCD
My assembler code has this error: "invalid program counter value: 0x00000000 Go: execution terminated with errors"
.data prompt2: .asciiz "please enter the elements one by one:" prompt3: .asciiz "the array is ordered as follows: " prompt4: .asciiz "-- Program is finished running --" str1: .asciiz "," newLine: .asciiz "\n" .text addi $sp,$sp,-24 sw $ra,0($sp) sw $s4,4($sp) sw $a2,8($sp) sw $s3,12($sp) sw $s0,16($sp) sw $s2,20($sp) main: # read n from console li $v0 5 syscall move $a2 $v0 #tagghiir t0 be a2 (n) # allocate dynamic memory sll $a0 $v0 2 # sll performs $a0 = $v0 x 2^2 li $v0 9 #9 is the system code for service(sbrk) whoes work is syscall #to allocate dynamic memory move $a1 $v0 #t2 saved address of heap #taghiir t2 to a1 #saved for printing li $v0, 4 # $system call code for print_str la $a0, prompt2 # $address of string to print syscall move $t1 $zero move $t4,$a1 inputLoop: bge $t1 $a2 exit1 # read in and store int li $v0 5 syscall sw $v0 0($t4) addi $t1 $t1 1 addi $t4 $t4 4 li $v0, 4 # $system call code for print_str la $a0, newLine # $address of string to print syscall j inputLoop exit1: jal sort li $v0, 4 # $system call code for print_str la $a0, prompt3 # $address of string to print syscall move $t3,$zero move $t4 ,$a1 outputLoop: bge $t3 $a2 exit2 #inaro azoon yki copy krdm lw $t6, 0($t4) li $v0, 1 move $a0, $t6 syscall # read in and store int addi $t3 $t3 1 addi $t4 $t4 4 blt $t4,$a1 ,comma # bne $t5,$zero,comma comma: li $v0, 4 # $system call code for print_str la $a0, str1 # $address of string to print syscall j outputLoop exit2: li $v0, 10 syscall #for finishing the program swap: move $a3,$a3 move $a1,$s4 # move $t5,$zero # its for our temp variable in c code move $t4 ,$a1 #t4 is now the base address of heap sll $t6 , $a3,2 # s1 is the given k add $t6,$t4,$t6 # heap address + k*4 lw $t3,0($t6) #khoone k e heap lw $t5,4($t6) #khoone k+1 heap sw $t5,0($t6) sw $t3,4($t6) jr $ra sort: # move $s0,$zero #i=t0 move $s4,$a1 #base address of heap addi $t5,$a2,-1 # meghdare i move $s2,$zero #its the flag while: addi $s2,$s2,1 move $a3,$zero #j #taghiir s1 be a3 (haman j va k forLoop: bge $a3,$t5,outOfLoop sll $t6,$a3,2 #j add $t1,$t6,$a1 #v+j lw $t7,0($t1) #t7=heap[j] lw $t8,4($t1) #t8=heap[j+1] blt $t7,$t8,outOfIf move $s4,$a1 move $s3,$a3 jal swap addi $s2,$s2,-1 outOfIf: addi $a3,$a3,1 #j++ outOfLoop: addi $t5,$t5-1 #i-- bgt $s2,$zero,exit_outter #if a>=b break ble $t5,$zero,exit_outter #if b=< c break j while exit_outter: lw $ra,0($sp) lw $s4,4($sp) lw $a2,8($sp) lw $s3,12($sp) lw $s0,16($sp) lw $s2,20($sp) addi $sp,$sp,24 jr $ra Where am I going wrong?
MIPS: Printing Out a Histogram
I'm writing a MIPS program (assembly language) that takes in 10 integers and prints out a histogram represented by asterisks. E.g.: User input of 1, 2, 3, 4 Output: * ** *** **** I have most of this code written already in MIPS. The problem I am running into is printing out the correct length of asterisks. As of now it is simply printing out the a histogram all of the same length; the FIRST user inputed integer. # program functionality: .data menu: .asciiz "\n1. New Histogram\n2. Print Histogram\n3. Quit\n" prompt: .asciiz "\nEnter 10 numbers between 0 and 50 (inclusive):\n" prompt1: .asciiz "\nEnter a valid number:\n" asterisk: .asciiz "*" space: .asciiz "\n" array: .word 0:10 .text main: do: jal print_menu li $v0, 5 syscall beq $v0, 1, new beq $v0, 2, print beq $v0, 3, quit j do # end do new: jal new_user j do print: jal print_user j do j quit print_menu: la $a0, menu li $v0, 4 syscall jr $ra new_user: la $a0, prompt li $v0, 4 syscall enter_loop: la $t0, array li $t1, 10 enter_loop_2: la $a0, prompt1 li $v0, 4 syscall li $v0, 5 syscall sw $v0, ($t0) addi $t1, $t1, -1 beqz $t1, end_loop_2 addi $t0, $t0, 4 j enter_loop_2 end_loop_2: jr $ra print_user: la $t0, array li $t1, 10 pLoop: la $a0, space li $v0, 4 syscall asterisk_fun: li $v0, 1 lw $a0, ($t0) syscall counter: la $a0, asterisk li $v0, 4 syscall addi $a0, $a0, -1 beqz $a0, asterisk_end j counter asterisk_end: jr $ra addi $t1, $t1, -1 beqz $t1, endpLoop addi $t0, $t0, 4 j pLoop endpLoop: jr $ra quit: li $v0, 10 syscall
The problems is that you are overwriting register $a0 in counter with the address of the asterisk, and you also used $a0 to count the number of items in that bucket. Easy solution is to use other register (e.g. $a1) to count the number of items: That would be: #... your code asterisk_fun: li $v0, 1 lw $a1, ($t0) # Load number in $a1 move $a0, $a1 # move to $a0 just to print it syscall la $a0, asterisk counter: li $v0, 4 syscall addi $a1, $a1, -1 # we use $a1 to keep the counter beqz $a1, asterisk_end j counter asterisk_end: # ... more of your code