J458
J458

Reputation: 5

Input Validation MIPS

How do I validate a user input in MIPS instruction set using MARS? In my following program I want to know how I can add validation to user input for example when asking the user if they want to decrypt or encrypt a message they need to input either 'E' or 'D' (case sensitive due to ascii values). As well as an input from (1-9) which is the encryption or decryption key. If they enter anything other than 'E', 'D' and a number from 1-9 how do I ask the user to enter a valid input using a subroutine for each prompt?

Code:

.data
    encrypt_decrypt: .asciiz "Type(E)ncrypt/(D)ecrypt:"
    key: .asciiz "\nEnter encryption key (1-9): "
    message_prompt: .asciiz "\nEnter message: "
    output: .asciiz ""
    re_enter: .asciiz "\nWrong input"
    buffer: .space 50
.text

main: 
    # Prints the prompt asking the user if they want to encrypt or decrypt
    li $v0, 4
    la $a0, encrypt_decrypt # Loads address from the user prompt
    syscall

    # Takes in E OR D based on user choice
    li $v0, 12      
    syscall
    add $t6, $v0, $0    
    bne $t6, 69, ELSE # Branch to else if inputed value is not E

    # Prints the prompt asking the user for a message to either decrypt or 
    encrypt based on the users previous choice
    li $v0, 4
    la $a0, message_prompt # Loads address from the users message
    syscall

    # Takes the users message
    li $v0, 8
    la $a0, buffer
    lb $t0, 0($a0)
    li $a1, 48
    syscall
    la $s2, buffer

    # Asks the user for a key from 1-9
    li $v0, 4
    la $a0, key
    syscall


    # Takes the users key value from 1-9
    li $v0, 5
    syscall
    add $s0, $v0, $0    

    la $t0, ($s0)   # Loads key
    li $t1, 0       # Lower order bit to be toggled
    la $t2, ($s2)   # Load user message


    beq $t6, 69, encrypt # 69 Is the printable ASCII value of "E"
    beq $t6, 68, decrypt # 68 is the printable ASCII value of "D"
ELSE:
    bne $t6, 68, E_D_VALIDATION # Branch to E_D_VALIDATION if user input is not D

E_D_VALIDATION:
    li $v0, 4
    la $a0, re_enter
    syscall
    j main  

encrypt: 

encrypt_loop: 

    lb   $t3, 0($t2)        # Loads character bytes
    beq  $t3, 10, encrypted # Branches to "encrypted" if we reach the end of a character
    add  $t3, $t3, $t0
    addi $t4, $0, 1       
    sllv   $t4, $t4, $t1    
    xor   $t3, $t3, $t4     # Lower order bit toggle

    sb   $t3, 0($t2)        # Stored encrypted character
    addi $t2, $t2, 1
    j encrypt_loop      # Loops through the list of encrypted characters
    
 encrypted:     
    li $v0, 4               # Print out encrypted message
    la $a0, output
    syscall
    la $a0, ($s2)
    syscall
    
    j exit              # Exits the program


decrypt: 
decrypted_loop:
    lb $t3, 0($t2)         # Loads character bytes
    beq $t3, 10, decrypted # Branches to "decrypted" if we reach the end of a character
    addi $t4, $0, 1
    sllv $t4, $t4, $t1
    xor $t3, $t3, $t4
    sub $t3, $t3, $t0
    sb $t3, 0($t2)        # Stored decrypted character
    addi $t2, $t2, 1

    j decrypted_loop      # Loops through the list of decrypted characters


decrypted: 
    li $v0, 4            # Print out decrypted message
    la $a0, output
    syscall
    la $a0, ($s2)
    syscall

    j exit              # Exit the program


    exit:

Upvotes: 0

Views: 1839

Answers (1)

Erik Eidt
Erik Eidt

Reputation: 26656

All you're missing is the error handling:

    beq $t6, 69, encrypt # 69 Is the printable ASCII value of "E"
    beq $t6, 68, decrypt # 68 is the printable ASCII value of "D"

    <handle error here>
     
encrypt: 

What to do to handle the error: print a message and quit, or print a message and goto someplace earlier in the code, maybe main or some other new label you introduce for this.


However, it might be nice to check for incorrect input before getting this far, and if you do that you won't have to check so much later: you can check for just E or just D instead of for both, because at this point you know it is only one or the other and nothing else.

So pseudo code you want to put immediately after inputting what should be the E or D:

if ( input != E && input != D ) { print input error message; goto reEnter; }

Where reEnter could be main or another location you choose to go back to get the input.

I would translate this into assembly language using the following series of transformations.

First, if-goto-label style, which skips the if-statement's then part when the condition is false:

    if ( ! ( input != E && input != D ) ) goto inputOk;
    print input error message
    goto reEnter;
inputOk:
    ; continue with rest of program knowing good input (exactly E or D)

Next: distribute the negation per De Morgan:

    if ( ! ( input != E ) || ! ( input != D ) ) goto inputOk;
    print input error message
    goto reEnter;
inputOk:
    ; continue with rest of program knowing good input (exactly E or D)

Next: negate the relational operators:

    if ( input == E || input == D ) goto inputOk;
    print input error message
    goto reEnter;
inputOk:
    ; continue with rest of program knowing good input (exactly E or D)

Next: split the disjunction (||)

    if ( input == E ) goto inputOk;
    if ( input == D ) goto inputOk;
    print input error message
    goto reEnter;
inputOk:
    ; continue with rest of program knowing good input (exactly E or D)

Now, that's pretty easy to write in assembly.

Upvotes: 1

Related Questions