Search code examples
stringassemblymipsuser-input

String input in MIPS omits the first four characters that are inputted


.data
EntryReq:
    .asciiz "Please enter an 8 digit hexadecimal MIPS instruction: \n"
InputLongError:
    .asciiz "\nYour input was too long, make sure it is 8 digits. "
InputShortError:
    .asciiz "\nYour input was too short, make sure it is 8 digits. "
CharInvalidError:
    .asciiz "\nYour input contains an invalid character. "
ValidChars:
    .asciiz "0123456789abcdef\n\b\0"

.align 4
input:
    .space 20

.text

main:
    #Print input request
    la $a0, EntryReq #loads input into arg. reg.
    li $v0, 4 #op code for print string
    syscall

    #take input for input (stored)
    li $v0, 8 #op code for take user input
    la $a0, input #provide address for syscall
        li $a1, 20 # tell syscall the byte space required for the string
    syscall

    #move to input(stored)
    sw $v0, input #move inputted into from $v0 to input(stored)

    #check validity of input
    la $a0, input #load address of input to arg. reg. for method call
    la $a1, ValidChars #load address of string of valid chars
    jal verifyInput #call the verifyInput method which does as expected 

    #test if string length count works
    addi $a0, $v0, 0 #load from $v0 to arg. reg.
    li $v0, 1 #op code for print int
    syscall

terminate:
    li $v0, 10
    syscall

verifyInput:
    li $v0, -1 #start length count at 0
verifyLoop:
    lb $t0, ($a0) #load current 
    li $a2, 0 #loop for char check, loops up to length of validChar string
    la $a1, ValidChars
    j checkChar
charVerified: #ignore this, is entry point back into verifyLoop for checkChar
    addi $a0, $a0, 1 #increment 
    addi $v0, $v0, 1
    bgt $v0, 8, printTooLongError #if result bigger than 8, error
    bne $t0, 10, verifyLoop #10 is string end, so check if string is end
    blt $v0, 8, printTooShortError #if result less than 8, error
    jr $ra #if here string input was confirmed okay

checkChar: # loops through valid chars for each char in $a0                 | Valid Chars: 0123456789abcdef\n |
    lb $t1, ($a1) #loads in byte from char string
    addi $a1, $a1, 1 #increment address, for the next char
    addi $a2, $a2, 1 #increment until length of valid char string is reached
    beq $t0, $t1, charVerified
    bne $a2, 19, checkChar #if length of valid chars changes, change second argument here
    j charNotValidError
charNotValidError:
    la $a0, CharInvalidError #loads input into arg. reg.
    li $v0, 4 #op code for print string
    syscall
    j terminate
printTooLongError:
    la $a0, InputLongError #loads input into arg. reg.
    li $v0, 4 #op code for print string
    syscall
    j terminate
printTooShortError:
    la $a0, InputShortError #loads input into arg. reg.
    li $v0, 4 #op code for print string
    syscall
    j terminate

The general gist of this code is for the user to input an 8 digit hexadecimal string, and then the program checks whether it is a valid hexadecimal string (i.e. includes only 0-9 and a-f). However, whenever I run it, the string that I input is missing the first four characters. So if I place invalid characters in the first four digits, like wwww1abc, then the code runs fine, which it shouldn't. But if I do 1abcwwww, it outputs an invalid character error, which it should. I'm genuinely confused as to why this is the case, nor have I seen anyone else experience this issue. Any help is greatly appreciated.


Solution

  • The problem is this line:

    #move to input(stored)
    sw $v0, input #move inputted into from $v0 to input(stored)
    

    Unlike read integer syscall, read string puts the result in the input buffer, in your case input. So you don't need to read out the value in $v0 and by storing it in input you're overwriting the first 4 bytes of the buffer with the value of $v0, which is still 0x00000008, which conveniently is the same as the string "\b\0\0\0" for little endian machines, all of which are in your validity list. Removing that line should fix your program (though I didn't look over all the rest of the code for errors).