I am currently working on an assignment for an Assembly Language class and have hit a wall with why it is not working properly.
I need to count the occurrence of each alphabetical letter (a-z) into a 26 integer word array (array[0] == occurrence of a; array[25] == occurrence of z). I then need to print the first 13 elements of the array separated by spaces, print a new line, and print the last 13 elements of the array separated by spaces.
I had the print function working with an array initiated to all 0s, then I had it working while only counting the occurrence of a. I have now modified the program to count all occurrences, which is working, but now my spaces between integers and the new line do not print.
Here is my code:
.data
array: .word 0:26
space: .asciiz " "
nLine: .asciiz "\n"
string: .asciiz "abbcccddddeffggghhhhijjkkkllllmnnoooppppqrrsssttttuvvwwwxxxxyzz"
bye: .ascii "\n**** Thank you for running my program ****\n"
.asciiz "\n**************** Goodbye *****************"
.text
main:
addi $t0, $zero, 0 # clear $t0
li $t3, 10 # 10 is ASCII for new line
li $t4, 97 # 97 is ASCII for 'a'
li $s0, 0 # counter for number occurence
li $t5, 0 # initiate counter for array position
la $t1, string # load address of string into $t1
count:
sw $s0, array($t5) # store letter count in array at position $t5
lb $t2, ($t1) # load next character of string
beq $t5, 104, reset # print once end of array reached
beq $t2, $t3, nArray # once end of string is reached move to next array element
beq $t2, $t4, inc # if letter matches, increment count
addi $t1, $t1, 1 # if letter does not match, move to next character in string
j count # loop
inc:
addi $s0, $s0, 1 # increment count
addi $t1, $t1, 1 # next character in string
j count # loop
nArray:
addi $s0, $zero, 0 # clear $s0
la $t1, string # load address of string into $t1
addi $t4, $t4, 1 # move to next ASCII letter
addi $t5, $t5, 4 # move to next array element
j count # loop
reset:
addi $t0, $zero, 0 # clear $t0
addi $t1, $zero, 0 # clear $t1
addi $t2, $zero, 0 # clear $t2
addi $t3, $zero, 0 # clear $t3
addi $t4, $zero, 0 # clear $t4
addi $t5, $zero, 0 # clear $t5
addi $t6, $zero, 0 # clear $t6
printA1:
beq $t0, 104, done # once through 26 words, end
beq $t0, 52, printNl # once through 13 words, print new line
printA2:
lw $t6, array($t0) # load next array element
addi $t0, $t0, 4 # increment array position
li $v0, 1 # load syscall code for print_int
move $a0, $t6 # move array element value into syscall argument
syscall # print integer
li $v0, 4 # load syscall code for print_string
la $a0, space # load space into syscall argument
syscall # print space
j printA1 # loop
printNl:
li $v0, 4 # load syscall code for print_string
la $a0, nLine # load new line into argument for syscall
syscall # print new line
j printA2 # loop
done:
li $v0, 4 # system call code for print_string
la $a0, bye # load address of message into $a0
syscall # print the string
li $v0, 10 # terminate program run and
syscall # return control to system
# END OF PROGRAM
And here is what is being output for string "abbcccddddeffggghhhhijjkkkllllmnnoooppppqrrsssttttuvvwwwxxxxyzz":
12341234123412341234123412 **** Thank you for running my program ****
**************** Goodbye ***************** -- program is finished running --
Any ideas what is causing it to skip the spaces and the new line? I did not modify those lines after having it working with all 0s and 1 letter other than adding the register reset beforehand.
You store a value into array($t5)
BEFORE you check that it has reached 104. After you read the z's, $t5 will be 104 and $s0 will be 0. You jump back to count
, at which point you store 0 into array(104)
, which runs off the end of the array and stores zeros in both space
and nLine
.
You are approaching this problem in the wrong way. Your code has deeply ingrained assumptions about what the string looks like. What if you were passed a string that did not have 26 different letters? What if the array were not in alphabetical order? Your loop should stop when you reach the zero terminator, and you should compute the bin number to increment by using $t2-97
, not by incrementing $t5
.
Your main loop should look like this:
count:
lb $t2, ($t1) # load next character of string
beq $t2, 0, print # if end of string
sub $t2, $t2, $t4 # convert letter value to ordinal
sll $t2, $t2, 2 # times 4
lw $t0, array($t2) # fetch the counter
addi $t0, $t0, 1 # bump it
sw $t0, array($t2) # store it
addi $t1, $t1, 1 # if letter does not match, move to next character in string
j count # loop