Arrays Mips程序无限循环问题
我现在正试图弄明白为什么我的火星程序创建阵列会陷入无限循环。我正在尝试使用不同的函数创建一个数组,在create array函数中,程序应该跳入一个get number函数并返回值以将其存储到数组中,但计数器似乎没有递减,它只是不断为数组请求一个元素。代码如下:Arrays Mips程序无限循环问题,arrays,loops,mips,Arrays,Loops,Mips,我现在正试图弄明白为什么我的火星程序创建阵列会陷入无限循环。我正在尝试使用不同的函数创建一个数组,在create array函数中,程序应该跳入一个get number函数并返回值以将其存储到数组中,但计数器似乎没有递减,它只是不断为数组请求一个元素。代码如下: .data str5: .asciiz "Please enter a number of elements for the array between 0 and 20: " str6: .asciiz "Please
.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, $0
jal verify
add $a0, $v0, $0
jal createarray
la $s1, array
jal printarray
li $v0, 10
syscall
printarray:
createarray:
add $t0, $ra, $0
add $s0, $a0, $0
add $t9, $0, $0
la $s1, array
loop:
beq $s0, 0, done
li $v0, 4
la $a0, str6
syscall
jal readnum
add $t1, $v0, $0
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, $0
jr $ra
verify:
add $s0, $a0, $0
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, $0
jr $ra
readnum:
li $v0, 5
syscall
jr $ra
编辑:重新读取代码后,导致错误的实际上是以下代码:
jal printarray
您从未在printarray中执行过以下代码:
jr $ra
因此,它将返回到其他函数
使用
$sp
(在函数中调用函数时处理$ra
的正确方法)
以下部分是问题的原因:
更具体地说是日航的呼叫。在函数中调用函数需要执行更多步骤
首先,了解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)
lw $ra, ($sp)
addi $sp, $sp, 4 # by convention, we use positive numbers when popping
为了在调用函数(首先替换了我们的$ra
)后获得我们曾经的位置,我们弹出堆栈:
addi $sp, $sp, -4 # by convention, we use negative numbers when pushing
sw $ra, ($sp)
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, $0
jal verify
add $a0, $v0, $0
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, $0
add $s0, $a0, $0
add $t9, $0, $0
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, $0
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, $0
jr $ra
verify:
add $s0, $a0, $0
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, $0
jr $ra
readnum:
li $v0, 5
syscall
jr $ra
编辑:重新读取代码后,导致错误的实际上是以下代码:
jal printarray
您从未在printarray中执行过以下代码:
jr $ra
因此,它将返回到其他函数
使用
$sp
(在函数中调用函数时处理$ra
的正确方法)
以下部分是问题的原因:
更具体地说是日航的呼叫。在函数中调用函数需要执行更多步骤
首先,了解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)
lw $ra, ($sp)
addi $sp, $sp, 4 # by convention, we use positive numbers when popping
为了在调用函数(首先替换了我们的$ra
)后获得我们曾经的位置,我们弹出堆栈:
addi $sp, $sp, -4 # by convention, we use negative numbers when pushing
sw $ra, ($sp)
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, $0
jal verify
add $a0, $v0, $0
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, $0
add $s0, $a0, $0
add $t9, $0, $0
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, $0
sw $t1, 0($s1)
addi $s1, $s1, 4
addi $s0, $s0, -1
addi $t9, $t9, 1
j loop
done:
add $ra, $t0, $0
jr $ra
verify:
add $s0, $a0, $0
bge $s0, 20, begin
ble $s0, 0, begin
add $v0, $s0, $0
jr $ra
readnum:
li $v0, 5
syscall
jr $ra