0

So I'm trying to simply take a user inputted string, and store that string into a register for comparison later on. I'm doing this by allotting bytes for the input buffer using the stack:

addi $a0, $sp, 2, and then using the syscall convention for string input (8). Then the user can enter either +,-,*,/, or %.

Then this char is supposed to be loaded into the register of my choosing move $s0, $a0. But it appears that the char is not being loaded into the register like I intend, because the comparisons to the register all fail, and in the memory view I can see that the hex is not equivalent to the input I'm giving it ("+" in this example) Any help?

Full source for clarity:

.data
    prompt: .asciiz "\nEnter operation +,-,*,%, or / (type q to quit): "
    prompt2: .asciiz "\nEnter left and right operands: "
    space: .asciiz " "
    equal: .asciiz " = "
.text
main:
    #Storage:
    # OP :          2 bytes $s0
    # Left:         4 bytes $s1
    # Right:        4 bytes $s2
    # RA Register:  4 bytes $ra
    # Result    4 bytes $s3
    addi $sp, $sp, -24
    sw $s0, 0($sp)
    sw $s1, 4($sp)
    sw $s2, 8($sp)
    sw $s3, 12($sp)
    sw $ra, 16($sp)
    while_loop_head:
        li $s3, 0
        lw $s0, 0($sp)
# --------------------- FIRST PROMPT ---------------------------------------------
        li $v0, 4 # prepare for print string system call
        la $a0, prompt # load prompt into argument register for syscall
        syscall # prints prompt
        
# ------------------ OP INPUT ---------------------------------------------------
        li $v0, 8 # prepare for string input
        addi $a0, $sp, 2 # prepare argument for syscall with char array space
        li $a1, 2 # limit of input is 2 bytes (first char and terminating null)
        syscall # asks user for op
        move $s0, $a0 # stores user input into $s0

# -------------------- SECOND PROMPT ------------------------------------------
        li $v0, 4 # prepare for print string system call
        la $a0, prompt2 # load prompt2 into argument register for syscall
        syscall # prints second prompt
        
# -------------------- LEFT AND RIGHT INPUT  ------------------------------------------     
        li $v0, 5 # prepare for integer input
        syscall # asks user for left int
        move $s1, $v0 # stores left int into $s1
        
        li $v0, 5 # prepare for integer input
        syscall # asks user for right int
        move $s2, $v0 # stores right int into $s2
        
        li $t1, '+'
        li $t2, '-'
        li $t3, '*'
        li $t4, '/'
        li $t5, '%'
        li $t6, 'q'
        
        beq $t1, $s0, Addition
        beq $t2, $s0, Subtraction
        beq $t3, $s0, Multiplication
        beq $t4, $s0, Division
        beq $t5, $s0, Modulo
        beq $t6, $s0, EXIT
    result:
        # print left
        li $v0, 1
        move $a0, $s1
        syscall 
        # print SPACE op SPACE
        li $v0, 4
        la $a0, space
        syscall
        li $v0, 4
        move $a0, $s0
        syscall
        li $v0, 4
        la $a0, space
        syscall
        # print right
        li $v0, 1
        move $a0, $s2
        syscall
        # print equal SPACE
        li $v0, 4
        la $a0, equal
        syscall
        li $v0, 4
        la $a0, space
        syscall
        # print result
        lw $s3, 12($sp)
        li $v0, 1
        move $a0, $s3
        syscall
        # return to while loop
        j while_loop_head
            
# -------------------------- CASES ----------------------------------------------------
    Addition:
        add $s3, $s1, $s2
        sw $s3, 12($sp)
        j result
    Subtraction:
        sub $s3, $s1, $s2
        sw $s3, 12($sp)
        j result
    Multiplication:
        mult $s1, $s2
        mflo $s3
        sw $s3, 12($sp)
        j result
    Division:
        div $s1, $s2
        mflo $s3
        sw $s3, 12($sp)
        j result
    Modulo:
        div $s1, $s2
        mfhi $s3
        sw $s3, 12($sp)
        j result
    EXIT:
        lw   $s0, 0($sp)
        lw   $s0, 4($sp)    
        lw   $s1, 4($sp)
        lw   $s2, 8($sp)
        lw   $s3, 12($sp)
        lw   $ra, 16($sp)
        addi $sp, $sp, 24
        li $v0, 10
        syscall

I should also mention that I am NOT using global variables, which is my reason for using the stack to allocate bytes as opposed to .space 2

1
  • $a0 doesn't contain the characters, it contains the address where the characters are stored. Commented Jul 29, 2020 at 6:59

1 Answer 1

1

So the answer to my question here can be summed up in 3 points.

  1. addi $a0, $sp, 2 is specifying a memory location from the stack pointer + 2. This means that anything at this location in memory will be overwritten by whatever the user inputs. So when allocating stuff on the stack, it's a good idea to keep that in mind. So this line should instead become addi $a0, $sp 16, as $sp+16 is unoccupied space (referring to the beginning of the code where I allocate space for the saved registers)

  2. As one user pointed out, the input buffer, $a0 in this case, is not receiving a string. It's receiving an address to that string. So when I do move $s0, $a0, it's not moving a string into $s0. The solution to this is to dereference the address in $a0, thereby, grabbing it's value. So this line should instead become lh $s0, 16($sp). This means to load 2 bytes from the memory location of $sp+16, and place them into $s0.

  3. After this, the user input is being received correctly, and the only issue that arises from this is that when reprinting the user input, you cannot use the systemcall for strings, but rather for a char instead. So instead of:

li $v0, 4 # code for string print
move $a0, $s0
syscall

It should be:

li $v0, 11 # code for char print 
move $a0, $s0
syscall

After all of these changes, the code runs as intended.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.