Mips程序死循环问题
Mips program infinite loop issue
我目前正在尝试弄清楚为什么我的用于创建数组的 mars 程序陷入无限循环。我正在尝试使用不同的函数创建一个数组,在创建数组函数中,程序应该跳转到获取数字函数和 return 将其存储到数组中的值,但计数器似乎不会递减并且它只是不断要求数组的元素。这是代码:
.data
str5: .asciiz "Please enter a number of elements for the array between 0 and 20: "
str6: .asciiz "Please enter an element: "
array: .word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
main:
begin:
li $v0, 4
la $a0, str5
syscall
jal readnum
add $a0, $v0, [=10=]
jal verify
add $a0, $v0, [=10=]
jal createarray
la $s1, array
jal printarray
li $v0, 10
syscall
printarray:
createarray:
add $t0, $ra, [=10=]
add $s0, $a0, [=10=]
add $t9, [=10=], [=10=]
la $s1, array
loop:
beq $s0, 0, done
li $v0, 4
la $a0, str6
syscall
jal readnum
add $t1, $v0, [=10=]
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, [=10=]
jr $ra
verify:
add $s0, $a0, [=10=]
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, [=10=]
jr $ra
readnum:
li $v0, 5
syscall
jr $ra
编辑:重新阅读代码后,导致错误的实际上是以下代码:
jal printarray
您从未在 printarray 中执行过以下代码:
jr $ra
所以,它会回到其他功能。
使用$sp
(在函数内调用函数时处理$ra
的正确方法)
以下段是问题的原因:
syscall
jal readnum
add $t1, $v0, [=12=]
更具体地说是 jal
调用。在函数内调用函数需要执行更多步骤。
首先,了解jal
指令的作用。 jal
指令,简单地说,标记你当前所在的位置,并将其存储在 $ra
寄存器中。然后,它会跳转到那个函数。
但是有一个问题:您已经希望 $ra
寄存器记住您曾经在哪里,因为实际上您叫 createarray
!
因此,您调用了 createarray
,使 $ra
存储您曾经所在的位置,然后在您调用 readnum
的函数中,使 $ra
存储您所在的位置createarray
。 **但是现在,你已经失去了你在被叫 createarray
之前所在的位置。因此,它将不断循环回到 $ra
曾经是什么,它在你的 createarray
函数中。
幸运的是,$sp
寄存器正是您所需要的
如何使用$sp
寄存器
为了存储我们所在的位置,我们压入堆栈:
addi $sp, $sp, -4 # by convention, we use negative numbers when pushing
sw $ra, ($sp)
为了在我们调用函数(首先取代我们的 $ra
)之后到达我们曾经所在的位置,我们弹出堆栈:
lw $ra, ($sp)
addi $sp, $sp, 4 # by convention, we use positive numbers when popping
所以在宏大的范围内,这就是你要做的:
# push to the stack
addi $sp, $sp, -4
sw $ra, ($sp)
jal theFunctionWeWantToCallInOurFunction
# pop the stack, get back our $ra
lw $ra, ($sp)
addi $sp, $sp, 4
让我们将此解决方案应用于您的代码库:
.data
str5: .asciiz "Please enter a number of elements for the array between 0 and 20: "
str6: .asciiz "Please enter an element: "
array: .word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
main:
begin:
li $v0, 4
la $a0, str5
syscall
jal readnum
add $a0, $v0, [=16=]
jal verify
add $a0, $v0, [=16=]
jal createarray
la $s1, array
jal printarray # comment off this line and you won't have an infinite loop
li $v0, 10
syscall
printarray:
createarray:
add $t0, $ra, [=16=]
add $s0, $a0, [=16=]
add $t9, [=16=], [=16=]
la $s1, array
loop:
beq $s0, 0, done
li $v0, 4
la $a0, str6
syscall
# store where we wish to come back to so that $ra can be overriden without losing data.
addi $sp, $sp, -4
sw $ra, ($sp)
# call the function. jal will replace our current $ra
jal readnum
# retrieve what our $ra once was
lw $ra, ($sp)
addi $sp, $sp, 4
add $t1, $v0, [=16=]
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, [=16=]
jr $ra
verify:
add $s0, $a0, [=16=]
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, [=16=]
jr $ra
readnum:
li $v0, 5
syscall
jr $ra
我目前正在尝试弄清楚为什么我的用于创建数组的 mars 程序陷入无限循环。我正在尝试使用不同的函数创建一个数组,在创建数组函数中,程序应该跳转到获取数字函数和 return 将其存储到数组中的值,但计数器似乎不会递减并且它只是不断要求数组的元素。这是代码:
.data
str5: .asciiz "Please enter a number of elements for the array between 0 and 20: "
str6: .asciiz "Please enter an element: "
array: .word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
main:
begin:
li $v0, 4
la $a0, str5
syscall
jal readnum
add $a0, $v0, [=10=]
jal verify
add $a0, $v0, [=10=]
jal createarray
la $s1, array
jal printarray
li $v0, 10
syscall
printarray:
createarray:
add $t0, $ra, [=10=]
add $s0, $a0, [=10=]
add $t9, [=10=], [=10=]
la $s1, array
loop:
beq $s0, 0, done
li $v0, 4
la $a0, str6
syscall
jal readnum
add $t1, $v0, [=10=]
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, [=10=]
jr $ra
verify:
add $s0, $a0, [=10=]
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, [=10=]
jr $ra
readnum:
li $v0, 5
syscall
jr $ra
编辑:重新阅读代码后,导致错误的实际上是以下代码:
jal printarray
您从未在 printarray 中执行过以下代码:
jr $ra
所以,它会回到其他功能。
使用$sp
(在函数内调用函数时处理$ra
的正确方法)
以下段是问题的原因:
syscall
jal readnum
add $t1, $v0, [=12=]
更具体地说是 jal
调用。在函数内调用函数需要执行更多步骤。
首先,了解jal
指令的作用。 jal
指令,简单地说,标记你当前所在的位置,并将其存储在 $ra
寄存器中。然后,它会跳转到那个函数。
但是有一个问题:您已经希望 $ra
寄存器记住您曾经在哪里,因为实际上您叫 createarray
!
因此,您调用了 createarray
,使 $ra
存储您曾经所在的位置,然后在您调用 readnum
的函数中,使 $ra
存储您所在的位置createarray
。 **但是现在,你已经失去了你在被叫 createarray
之前所在的位置。因此,它将不断循环回到 $ra
曾经是什么,它在你的 createarray
函数中。
幸运的是,$sp
寄存器正是您所需要的
如何使用$sp
寄存器
为了存储我们所在的位置,我们压入堆栈:
addi $sp, $sp, -4 # by convention, we use negative numbers when pushing
sw $ra, ($sp)
为了在我们调用函数(首先取代我们的 $ra
)之后到达我们曾经所在的位置,我们弹出堆栈:
lw $ra, ($sp)
addi $sp, $sp, 4 # by convention, we use positive numbers when popping
所以在宏大的范围内,这就是你要做的:
# push to the stack
addi $sp, $sp, -4
sw $ra, ($sp)
jal theFunctionWeWantToCallInOurFunction
# pop the stack, get back our $ra
lw $ra, ($sp)
addi $sp, $sp, 4
让我们将此解决方案应用于您的代码库:
.data
str5: .asciiz "Please enter a number of elements for the array between 0 and 20: "
str6: .asciiz "Please enter an element: "
array: .word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
main:
begin:
li $v0, 4
la $a0, str5
syscall
jal readnum
add $a0, $v0, [=16=]
jal verify
add $a0, $v0, [=16=]
jal createarray
la $s1, array
jal printarray # comment off this line and you won't have an infinite loop
li $v0, 10
syscall
printarray:
createarray:
add $t0, $ra, [=16=]
add $s0, $a0, [=16=]
add $t9, [=16=], [=16=]
la $s1, array
loop:
beq $s0, 0, done
li $v0, 4
la $a0, str6
syscall
# store where we wish to come back to so that $ra can be overriden without losing data.
addi $sp, $sp, -4
sw $ra, ($sp)
# call the function. jal will replace our current $ra
jal readnum
# retrieve what our $ra once was
lw $ra, ($sp)
addi $sp, $sp, 4
add $t1, $v0, [=16=]
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, [=16=]
jr $ra
verify:
add $s0, $a0, [=16=]
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, [=16=]
jr $ra
readnum:
li $v0, 5
syscall
jr $ra