1

I have the program working, my only issue is the loop runs one extra time than it should which increments the consonant count one too many times. I can of course get around this by just subtracting 1 from the count at the end but I am curious why it is running an extra time. I've used the step feature to try and troubleshoot in PCSpim and I can see that $a0 = 0000000a instead of 00000000 on what should be the last loop. Why is this happening?

#################################################
#                       #
#               text segment            #
#                       #
#################################################

    .text
    .globl __start
__start:                # execution starts here

    la $a0,prompt1  # print prompt on terminal
    li $v0,4        # system call to print
    syscall         # out a string

    la $a0,string
    li $a1,20
    li $v0, 8   # syscall 8 reads string/letter
    syscall
    
    li $t1, 0   # register used to keep track of number of vowels
    li $t2, 0   # register used to keep track of number of consonances

    la $a1, string  # prepare for passing a letter to the procedure
    

loop:   
    lb $a0, 0($a1)  # load one character from the string
    beqz $a0, End   # if no more characters then go to End
    addi $a1,$a1,1  # increment address position to print next character in string

    jal vowelp  # procedure call

    move $t0,$v0    # save the value returned from the procedure call

    beqz $t0, NotVowel
    
    addi $t1, $t1, 1

    j loop

NotVowel:
    addi $t2, $t2, 1
    
    j loop
End:    
    la $a0, answer1
    li $v0, 4
    syscall
    
    move $a0, $t1
    li $v0, 1
    syscall     # print number of vowels

    la $a0,endl # syscall to print out
    li $v0,4    # a new line
    syscall     

    la $a0, answer2
    li $v0, 4
    syscall
    
    addi $t2, $t2, -1   

    move $a0, $t2
    li $v0, 1
    syscall     # print number of consonants

    la $a0,endl # syscall to print out
    li $v0,4    # a new line
    syscall 

    li $v0,10
    syscall     # Bye!

##############################################################
## Define the procedure vowelp
##############################################################

vowelp:

    li $v0, 0   # initialize $v0 to 0
    beq $a0,' ',loop
    beq $a0,'A',yes 
    beq $a0,'a',yes
    beq $a0,'E',yes
    beq $a0,'e',yes
    beq $a0,'I',yes
    beq $a0,'i',yes
    beq $a0,'O',yes
    beq $a0,'o',yes
    beq $a0,'U',yes
    beq $a0,'u',yes
    jr $ra
yes:    li $v0,1
    jr $ra
    

#################################################
#                       #
#               data segment            #
#                       #
#################################################

        .data
    string:     .space 20
    prompt1:    .asciiz "Enter a string: "
    
    answer1:    .asciiz "The number of vowels in the string is: \n"
    answer2:    .asciiz "The number of consonants is: \n"
    message:    .asciiz "The character entered is not a vowel."
    ans1:       .asciiz "The character entered is a vowel. "
    endl:       .asciiz "\n"       

##
  • BTW, there's a trick to make this *much* more efficient: check if the character is alphabetic and turn it into an index into the alphabet (ori / addiu -'a' / branch) ([Testing if a value is within one of two ranges](https://stackoverflow.com/a/66893955)), then use that index-into-the-alphabet for a lookup table. Or instead of a memory table, an integer bitmap in a register that you index with `srl $v0, $t1, $t0` / `andi $v0, $v0, 1` to grab the indexed bit, then `add $t1, $t1, $v0` to add the 0 or 1 to your count. (Adding 0 is a no-op, you don't need to branch to avoid it.) – Peter Cordes Apr 03 '21 at 18:02
  • [What is the compiler doing here that allows comparison of many values to be done with few actual comparisons?](https://stackoverflow.com/a/58115005) has more details about the idea of using an integer in a register as a bitmap. (With x86 asm, but same difference.) [User Appreciation Challenge #1: Dennis ♦](https://codegolf.stackexchange.com/a/123458) codegolf answer uses a bitmap of consonants: invert that and you have a vowel bitmap (i.e. `~0x3efbeee`). Or just count consonants and alphabetics, and do vowels = letters - consonants at the end, to correctly reject space, newline, etc. – Peter Cordes Apr 03 '21 at 18:03
  • (Your way isn't *wrong*, I'm just pointing out a more efficient way that might be fun to understand.) – Peter Cordes Apr 03 '21 at 18:06

0 Answers0