[英]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点。
addi $a0, $sp, 2
从堆栈指针 + 2 指定 memory 位置。这意味着 memory 中此位置的任何内容都将被用户输入的任何内容覆盖。 所以在堆栈上分配东西时,记住这一点是个好主意。 所以这一行应该改为addi $a0, $sp 16
,因为$sp+16
是未占用的空间(指的是我为保存的寄存器分配空间的代码的开头)
正如一位用户所指出的,输入缓冲区(在这种情况下为$a0
)没有接收到字符串。 它正在接收该字符串的地址。 因此,当我确实move $s0, $a0
时,它不会将字符串移动到$s0
中。 解决方案是取消引用$a0
中的地址,从而获取它的价值。 所以这条线应该改为lh $s0, 16($sp)
。 这意味着从$sp+16
的 memory 位置加载 2 个字节,并将它们放入$s0
中。
在此之后,用户输入被正确接收,由此产生的唯一问题是,在重新打印用户输入时,您不能将系统调用用于字符串,而是用于 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.