1
votes

Been trying to write this hex to decimal converter in MIPS. Should take in up to 8 arguments (string) from command line, all hex starting with "0x", 4 bytes long and terminated with null character after every argument.

$s1= number of args; $s0-->args(0).

For these Program Arguments: 0x1A 0xF1 0x0B3:

.data 
buffer: .space 32
args: .asciiz "\nProgram arguments:\n"
space: .asciiz " " 
d_rep: .asciiz "\n\nInteger values:\n"
newLine: .asciiz "\n"
maxVal: .asciiz "Maximum value:\n"

.text
main:
    
  
   
    add $t9, $zero, $zero        # t9 will be max value
    add $s1, $a0, $0        # store number of program arguments
    add $s2, $a1, $0        # store address of where program arguments are
    addi $s0, $0, 0     # use s0 as index for looping
    addi $s7, $zero, 0           # used as index for print loop
    add $s6, $s1, $0        # store numArgs for printloop
    add $s5, $s2, $0        # store address for printloop
    addi $t5, $zero, 16 
    addi $t6, $zero, 0 
     

    la $a0, args         # load and print "Program arguments" string
    li $v0, 4                     # print
    syscall
printloop:                       
    beq $s7, $s6, printInt        # only print as many times as there are args
    lw $a0, 0($s5)                # get the first word
    li $v0, 4                     # print
    syscall
    la $a0, space                 # print a space between words
    li $v0, 4                     # print
    syscall
    addi $s5, $s5, 4              # increment to next word
    addi $s7, $s7, 1              # increment printloop counter
    j printloop                   # loop again if there are more args
    
printInt:
     la $a0, d_rep                 # print "Decimal values:"
     li $v0, 4                     # print
     syscall
        
    
while:
        
    beq $s0, $s1, done         # while $s0 <= numArgs
    lb $t1, 2($s2)             # load s2[2] into 
       
         addu $t2, $zero, $t1       # make a copy so we dont lose place 
         subiu $sp, $sp, 4
convert:
 
     beqz $t2, postConv          # while t2 != null
      blt $t2, 65, convNumber    # if less than value of A then got a num
    
        subiu $t3, $t2, 0x37        # -55 for uppercase letter 
        sll $t3, $t3, 4          # sll by 4 is same as mult by 16
              
        sw $t3, ($sp)           # store word to do some addition
        addiu $t2, $t2, 1         # increment t2
        subiu $sp, $sp, 4         # increment sp
        j convert                # go back to convert 
        
convNumber:
    addu $t3, $zero, $t2       # put t2 into t3 for to do some math
    subiu $t3, $t3, 0x30         # -48 for number 
    sll $t3, $t3, 4           # sll by 4 is same as mult by 16
    sw $t3, ($sp)
    addiu $t2, $t2, 1          # increment t1
    addiu $sp, $sp, 4          # increment sp
     j convert                # jump back to convert 


postConv:  
     addi $sp, $sp, 4              # load the second value
      lw $s4, ($sp)               # load the first value
     addi $sp, $sp, 4
   # sll $s4, $s4, 4
     lw $s3 ($sp)  
    
     addu $s3, $s3, $s4            # add em up for converted decimal
         
     move $a0, $s3               # move to a0 so they pint
     li $v0, 1                    # print
     syscall
    
     addiu $s0, $s0, 1             # increment loop counter
     addiu $s2, $s2, 4             # increment to next word
     ble $t9, $t6, newMax         # check for a new max value
         j while                  # jump back to loop
    


newMax:
   
     addu $t9, $zero, $t6           # got a new max so save it
    j while

done:
  
  
    
    la, $a0, newLine
    li $v0, 4
    syscall
    
    la, $a0, newLine
    li $v0, 4
    syscall
    
    la, $a0, maxVal
    li $v0, 4
    syscall
    
    move $a0, $t9
    li $v0, 1
    syscall
    
    la, $a0, newLine
    li $v0, 4
    syscall 
    
   
    
      li $v0, 10               # end program
      syscall       
    

My output is this:

Program arguments:
0x1A 0xF1 0x0B3 

Integer values:
-2121474836290

Maximum value:
0

-- program is finished running --

But it should be : 26 241 179. And maxValue should be: 241

I would be very grateful if someone could help me debug this. Thank you! :D

1

1 Answers

1
votes

You should have be able to debug this yourself.  Single stepping the code to find this error is trivial.  If you don't know how to debug code, then suggest you focus on learning that.  Check each instruction to make sure it is doing what you expect, and if not, that's where the problem is.

argv is a pointer to pointers to characters — if we consider that a pointer to characters is a string, then we can describe argv as a pointer to strings.  To get single character from argv we have to choose which of the strings, then choose a character from that string.

You are doing this correctly when printing the program arguments, but are not following that approach for accessing their bytes, instead you're accessing individual bytes from the pointers themselves, which of course makes no sense.  Put another way, you're missing an indirection aka dereference.

This kind of error should stand out to you like a flashing warning sign when you single step over the lb $t1, 2($s2) instruction — because you are expecting it to fetch the ascii 1, 0x31, but are getting an 0xff instead.  When you see that an instruction is not getting what you expect that's where and when to rethink things: it is doing what you told it to do but you can observe that is not what you want.