2
\$\begingroup\$

I have written the following code for a programming assignment. I would appreciate some help to improve this code and see if it meets all the requirements and criteria. I would like to improve my loop and supporting continue function.

###############################
#String to int. 
###############################

#########################################################################             
##| The program obeys MIPS function calling convetions.
##|  
##| The program accepts two arguments for function stringToInt.
##| Argument A (testInput): address of null terminated string.
##| Argument B (base): An integer in the range of 2 and 16.
##| 
##| The program outputs an integer result converting the given
##| argument a into an integer.
##| If the second argument is not in the range of 2-16 the program 
##| returns error message and returns the value of zero. The same 
##| applies if the legal digits are not entered.      
##|
##| Legality of the input                                                                                 
##|     If the string has only the characters from '0' to '9'           
##|     and from 'a' to 'f' and from 'A' to 'F'           
##| Input starting with '-' is accetped '+' is illegal. 
##| If the digits are not legal:              
##|     The program prints out error message and returns value 0.  
##| 
##|   
##|_______________________________________________________________________#


#******************************Begin*************************************** 
.data
###############  Test Case ###################
  stringInput: .asciiz "-1234"  #String        
  base:        .byte 16         #Base (2-16)   
##############################################

  #Prints out error message.    
  errorMessage:  .asciiz "\nError. Please check input string."

.text  
###########################################################################
# Function: stringToInt
# Excepts two arguments string address and base. Loads base argument 
# into $a1 and char address into $t0. Converts string into ascii notation. 
# Checks the validity of base (between 2 and 16 incluseive) and if
# the input is negative. If negative convert it using twos complement. 
# If the base is not between 2-16 prints an error message return zero.
# Converts the string into integer. Terminates program at '\n' or '\0'. 

stringToInt: 

        la $t0, stringInput #current char address in t0
    li $t2, 0       #decimal equivalent intialized to 0
    li $t4, 1       #power 
    lb $a1, base        #load base into register a1
    bgt $a1, 16, invalid    #checks if base is valid

    lb $s6, base        #loads base into register s6 
    addi $s6, $s6, 48   # converts s6 to ascii notation
    lb $s0, ($t0)   
    la $t5, stringInput
    beq $s0, '-', negSet    #checks first element of string to see if it is a minus sign
    j check         #jump to check
#_________________________________________________________________________#

###########################################################################
# Checks if the nubmer is negative.     
negSet:
    addi $s7, $zero, 1  #s1 will store a value to check if no is negative 
    addi $t0, $t0, 1
    addi $t5, $t5, 1
#_________________________________________________________________________#

###########################################################################     
#Go till end of end of input
check:
    lb $t1, ($t0)
    beq $t1, '\n', endCheck
    beq $t1, '\0', endCheck
    add $t0, $t0, 1
    b check

endCheck:
#_________________________________________________________________________#

###########################################################################
# Go from last char to first, decrementing address. Compare from highest
# ascii value. If less than start address jummp to countinue4. Else invalid 
loop:
    sub $t0, $t0, 1
    blt $t0, $t5 , valid     #if less than start address stop
    lb $t1, ($t0)
    bgt $s6, 57, continue3   #compare from highest ascii value
    bge $t1, $s6, invalid    #branch to invaldi if  $t1 >= $s6
    j continue4      #jump to continue 4

# exit point if base is greater than 10
continue3:

# makes sure only needed values are used    
continue4:  
    bge $t1, 'g', invalid       
    bge $t1, 'a', lower
    bge $t1, 'G', invalid
    bge $t1, 'A', upper
    bge $t1, '9', invalid
    bge $t1 , '0', digit

#print error message and exit. 
invalid:
    li $v0,1
    li $a0,0
    syscall
    li $v0, 4
    la $a0, errorMessage         
    syscall
    b exit

#Peforms validity checks. 
#Check if the vlaue is negative. (Using twos complement)    
valid:
    addi $t1, $zero, 1
    sll $t1, $t1, 31
    and $s1, $t2, $t1 
    bne $s1, $zero, bignegative
    bne $s7, $zero, twosComplement  # checkes the s7 register to see if our value is negative

# Return point after converting to negative number if a minus sign 
# was detected. Print and exit.     
continue2:          
    li $v0, 1       # Print content of t2
    move $a0, $t2
    syscall
    b exit  

# manipulates the digit to convert and checks validity.   
digit:
    bgt $t1, '9', invalid
    sub $t3, $t1, '0'   #get numeric digit value
    mul $t3, $t3, $t4   #mulitply by the current power 
    add $t2, $t2, $t3
    mul $t4, $t4, $a1   #next power 
    j loop          #jump back to loop 

#get numeric digit value    
lower:
    bgt $t1, 'f', invalid 
    sub $t3, $t1, 'a'
    add $t3, $t3, 10
    mul $t3, $t3, $t4   #mulitply by the current power
    add $t2, $t2, $t3
    mul $t4, $t4, $a1   #next power 
    b loop          #branch to loop 

#get numeric digit value    
upper:
    bgt $t1, 'F', invalid

    sub $t3, $t1, 'A'
    add $t3, $t3, 10
    mul $t3, $t3, $t4   #mulitply by the current power 
    add $t2, $t2, $t3   #add to decimal
    mul $t4, $t4, $a1   #next power 
    b loop          #branch to loop 

bignegative:
    li $t7, 10      # load value 10 into register t7
    divu $t2, $t7
    mflo $t1        # move value of LO register into $t1
    mfhi $t7        # move value of HI register into $t7

    #Print t1
    add $a0, $t1, $zero
    li $v0, 1
    syscall

    # printt7
    add $a0, $t7, $zero
    li $v0, 1
    syscall

#Ends the program and exit.     
#tell the system this is the end of stringToInt 
exit:   
        li $v0, 10
        syscall

#Perform the twos complement by subracting zero. To convert 
#negative input.    
twosComplement:

    sub $t2, $zero, $t2     # convert number to negative
    j continue2             #jump to continue2 


#_________________________________________________________________________#
\$\endgroup\$
2
\$\begingroup\$

I'm not familiar with MIPS, but I can make some observations.

  • General impressions: well presented code with appropriate level of comments.

  • You do seem confused by the character coding:

    # Converts string into ascii notation
    

    That's the other way around - ASCII is the encoding of the characters into bytes, so what you're doing is requiring that the input string uses the ASCII encoding.

  • Does MIPS not have a bne instruction? This code always jumps:

        beq $s0, '-', negSet    #checks first element of string to see if it is a minus sign
        j check         #jump to check <-- OVERCOMMENT
    # Checks if the number is negative.     
    negSet:
        addi $s7, $zero, 1  #s1 will store a value to check if no is negative 
        addi $t0, $t0, 1
        addi $t5, $t5, 1
    check:
    

    By inverting the initial test, we can have one case that doesn't branch:

        bne $s0, '-', check    #checks first element of string to see if it is a minus sign
    # Number is negative.     
    negSet:
        addi $s7, $zero, 1
        addi $t0, $t0, 1
        addi $t5, $t5, 1
    check:
    
  • Here's a no-op jump (also with a comment that adds nothing to the code):

        j continue4      #jump to continue 4
    continue3:
    continue4:  
    
  • The tests here assume ASCII ordering:

    bge $t1, 'g', invalid       
    bge $t1, 'a', lower
    bge $t1, 'G', invalid
    bge $t1, 'A', upper
    bge $t1, '9', invalid
    bge $t1 , '0', digit
    

    That's not necessarily a problem in itself, but it does warrant a comment, so that if it has to be adapted to other encodings where 0..9, A..F, a..f, are in different orders (or, potentially, discontiguous), then it would be easier to find the part to be modified.

    I'm concerned that you may be counting 9 as an invalid digit in the above - has this code actually been tested with limit values? It would be clearer to write the tests in consistent form (0x9AxFaxf) rather than mixing 9 with < G|g.

    An alternative, flexible approach might be to define a table mapping character codes to their digit values, with a suitable marker for invalid (anything over 16 will work for us; FFh is a good choice). This trades a small amount of code for a (probably) faster lookup; it allows the table to be chosen at runtime to support different encodings. (I'm not necessarily recommending this, but it improves your learning experience if you at least consider how to do it, and what the costs and benefits would be.)

  • It shouldn't be necessary to perform separate validation and conversion steps. We can validate as we go, and jump out of the conversion at the point that we reach an invalid character for the base.

  • I don't see any check for overflow. What if the input number is too large to be represented?

  • Tests - you haven't presented any tests. I'd like to see tests confirming:

    • reject base 1.
    • reject base 17.
    • In any valid base, reject "" and "-".
    • In base 2, reject "2", "A" and "a", but accept "00" and "11".
    • In base 10, reject "A" and "a", but accept "00" and "99".
    • In base 11, reject "B" and "b", but accept "00", "99" and "0a".
    • In base 16, reject "G" and "g", but accept "09" and "af".
    • Test "-0", "-1" and a large negative value convert correctly.
    • Some additional tests of - other than as first character.
\$\endgroup\$
  • \$\begingroup\$ Dear Toby, Thank you for your good detailed analysis of my code. I am a beginner in MIPS assembly language. Yes, I have made some mistakes thanks for pointing them out. I will post some of my results. Also, another thing I noticed was that I did not follow MIPS calling conventions which I need to fix as well. \$\endgroup\$ – Anon_Singh Dec 13 '17 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.