繁体   English   中英

如何使用 MIPS 将用户输入加载到寄存器中?

[英]How to load user input into register using MIPS?

所以我试图简单地获取用户输入的字符串,并将该字符串存储到寄存器中以便稍后进行比较。 我通过使用堆栈为输入缓冲区分配字节来做到这一点:

addi $a0, $sp, 2 ,然后使用系统调用约定进行字符串输入 (8)。 然后用户可以输入 +、-、*、/ 或 %。

然后这个 char 应该被加载到我选择move $s0, $a0的寄存器中。 但似乎 char 没有像我想要的那样加载到寄存器中,因为与寄存器的比较都失败了,在 memory 视图中我可以看到十六进制不等于我给它的输入(“ +”在这个例子中)有什么帮助吗?

为清晰起见,完整来源:

.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

我还应该提到我没有使用全局变量,这是我使用堆栈而不是.space 2来分配字节的原因

所以我这里的问题的答案可以总结为3点。

  1. addi $a0, $sp, 2从堆栈指针 + 2 指定 memory 位置。这意味着 memory 中此位置的任何内容都将被用户输入的任何内容覆盖。 所以在堆栈上分配东西时,记住这一点是个好主意。 所以这一行应该改为addi $a0, $sp 16 ,因为$sp+16是未占用的空间(指的是我为保存的寄存器分配空间的代码的开头)

  2. 正如一位用户所指出的,输入缓冲区(在这种情况下为$a0 )没有接收到字符串。 它正在接收该字符串的地址。 因此,当我确实move $s0, $a0时,它不会将字符串移动到$s0中。 解决方案是取消引用$a0中的地址,从而获取它的价值。 所以这条线应该改为lh $s0, 16($sp) 这意味着从$sp+16的 memory 位置加载 2 个字节,并将它们放入$s0中。

  3. 在此之后,用户输入被正确接收,由此产生的唯一问题是,在重新打印用户输入时,您不能将系统调用用于字符串,而是用于 char。 所以而不是:

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

应该是:

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

在所有这些更改之后,代码按预期运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM