# MIPS assembly string to int function

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
# 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
#_________________________________________________________________________#

###########################################################################
# 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

#_________________________________________________________________________#


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.
• 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. – Anon_Singh Dec 13 '17 at 20:24