Search code examples
arraysstringloopsintegermips

Counting Letter Occurrence and Printing a Word Integer Array in MIPS


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.


Solution

  • 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