1
votes

I'm new to MIPS assembly language. Just started to learn. I've got this problem where I have to display a letter grade for the test score that the user inputs. I've done this so far, but I cannot get it to work. I always keep getting invalid or sometimes the program ends or gives a D.

It is assumed:

Score Range Letter Grade 
90 to 100 A 
80 to 89 B 
70 to 79 C 
60 to 69 D 
0 to 59 F 

Please help me figure out what I'm doing wrong and correct my code!

.data

prompt: .asciiz "Enter a test score [0 to 100] or -1 to stop: "
invalidPrompt:  .asciiz "Invalid \n"
A:  .asciiz "A \n"
B:  .asciiz "B \n"
C:  .asciiz "C \n"
D:  .asciiz "D \n"
F:  .asciiz "F \n"

.globl main
.text

main:
    li $v0, 4
    la $a0, prompt
    syscall

    li $v0, 5
    syscall
    #move $a1, $v0

    beq $v0, -1, end    # -1 to stop

checkA:              
    bge $v0, 90, checkB
    ble $v0, 100, checkB
    li $v0, 4
    la $a0, A
    syscall
#    j main

checkB:       
    bge $v0, 80, checkC
    ble $v0, 89, checkC
    li $v0, 4
    la $a0, B
    syscall 
 #   j main

checkC:    
    bge $v0, 70, checkD
    ble $v0, 79, checkD 
    li $v0, 4
    la $a0, C
    syscall 
#    j main

checkD:    
    bge $v0, 60, checkF
    ble $v0, 69, checkF 
    li $v0, 4
    la $a0, D
    syscall 
#    j main  

checkF:    
    #bge $v0, 0, invalid
    ble $v0, 59, end
    li $v0, 4
    la $a0, D
    syscall 
#    j main

invalid:    
    blt $v0, 0, end
    bge $v0, 100, end
    li $v0, 4
    la $a0, invalidPrompt
    syscall
#    j main                                          
j main

end:

#--- TERMINATE ---
      li $v0, 10       # terminate program run and
      syscall          # return control to the OS.  

The second part of the problem is I have to display the number of A's, B's and so on after user enters -1. How can I go about this? I know I have to store the count of each grade when true in a separate register and keep incrementing but not sure how this is done.

Edit: I am using MARS 4.1 tool on Windows 7.

2

2 Answers

1
votes

Part 1:

checkA:              
bge $v0, 90, checkB
ble $v0, 100, checkB

Here you test if $v0 is between 90 and 100, and then jump to checkB. You must check if it is not between 90 and 100:

checkA:              
ble $v0, 90, checkB
bge $v0, 100, checkB

Part 2: Just initialize $t1 to $t5 to zero, and increment $t1 when A, $t2 when B, ...

1
votes

You have your logic backwards. GE = GREATER THAN OR EQUAL LE = LESS THAN OR EQUAL

Also you don't really need the logical AND operator at all if you start with the smallest and work your way up.

  • IF grade == -1 THEN EndProgram
  • IF grade < 0 THEN Error
  • IF grade < 60 THEN F
  • IF grade < 70 THEN D
  • IF grade < 80 THEN C
  • IF grade < 90 THEN B
  • IF grade < 100 THEN A
  • ; grade must be greater than 100 so Error
main:
    li $v0, 4
    la $a0, prompt
    syscall

    li $v0, 5
    syscall
    #move $a1, $v0

    beq $v0, -1, end    # -1 to stop

    ble $v0, 0, invalid 

checkF:
    bge $v0, 60, checkD
    li $v0, 4
    la $a0, F
    syscall
    j main
checkD:
    bge $v0, 70, checkC
    li $v0, 4
    la $a0, D
    syscall
    j main
checkC:
    bge $v0, 80, checkB
    li $v0, 4
    la $a0, C
    syscall
    j main
checkB:
    bge $v0, 90, checkA
    li $v0, 4
    la $a0, B
    syscall
    j main
checkA:
    bge $v0, 101, invalid
    li $v0, 4
    la $a0, A
    syscall
    j main
invalid:    
    li $v0, 4
    la $a0, invalidPrompt
    syscall

    j main

end:

      li $v0, 10       # terminate program run and
      syscall          # return control to the OS.