分区功能的错误(MIPS组件)
这是我编写的代码,试图在MIPS中实现C分区功能。 似乎存在错误,因为该程序不起作用,但我找不到它在哪里。 我知道最好调试它,但是我不知道该如何调试。我也对存储和恢复寄存器感到困惑,也许问题在于那里。
另外,我在Visual Studio中安装了MIPS组件调试器,但是该应用程序无法识别它,似乎没有其他MIPS选项。
partition:
#int partition(int f, int l) {
# int pivot = v[l];
# int i = f;
# for (int j = f; j < l; j++)
# if (v[j] < pivot)
# swap(i++,j);
# swap(i, l );
# return (i);
#}
addi $sp, $sp, -24 #make room for 6
sw $a0, 0($sp) #store f
sw $a1, 4($sp) #store l
sw $ra, 8($sp) #store return address
sw $t2, 12($sp) #store i
#sw $t3, 16($sp) #store j
sw $t1, 16($sp) #store pivot
sw $s0, 20($sp) #store s0
la $s0, v # s0 = address of v
sll $t0, $a1, 2 # t0 = 4*l
add $t0, $s0, $t0 # t0 = address of v[l]
lw $t1, 0($t0) # t1 = v[l], t1 = pivot
move $t2, $a0 # t2 = i, t2 is f
move $t3, $a0 # t3 = j, t3 is f
for1:
slt $t4, $t3, $a1 #if(j<l) t4=1
beq $t4, $zero, end1 #goto end1 if t4 = 0
sll $t4, $a0, 2 # t4 = 4*j
add $t4, $s0, $t4 #t4 = address of v[j]
lw $t5, 0($t4) #t5 = v[j]
slt $t6, $t5, $t1 # if (v[j] < pivot) t6=1 else t6=0
bne $t6, $zero, else
move $a0, $t2 #a0 = i
move $a1, $t3 # a1 = j
jal swap # swap(i++,j);
addi $t2, $t2,1 # i++
else:
addi $t3, 1 #j++
j for1
#here stops the for1 loop
end1: #come here when exiting the for1 loop
# a0=f & a1=l
move $a0, $t2 #a0 = i
lw $a1, 4($sp) #a1= l
jal swap
move $v0, $a0 #v0=i / return i
lw $ra, 8($sp) #restore ra
lw $s0, 20($sp) #restore s0
lw $a0, 0($sp) #restore a0
lw $a1, 4($sp) #restore a1
#lw $s1, 4($sp) #restore s1
addi $sp, $sp, 24 #restore stack
jr $ra
This is the code I wrote trying to implement the c partition function in mips.
There seems to be an error because the program doesn't work, yet I can't find where it is.
I know it would be best to debug it, but I don't know how to debug. Also I am kind of confused about storing and restoring registers, perhaps the problem lies there.
Also I installed a mips assembly debugger in visual studio but the application doesn't recognize it and there seems to be no other options for mips.
partition:
#int partition(int f, int l) {
# int pivot = v[l];
# int i = f;
# for (int j = f; j < l; j++)
# if (v[j] < pivot)
# swap(i++,j);
# swap(i, l );
# return (i);
#}
addi $sp, $sp, -24 #make room for 6
sw $a0, 0($sp) #store f
sw $a1, 4($sp) #store l
sw $ra, 8($sp) #store return address
sw $t2, 12($sp) #store i
#sw $t3, 16($sp) #store j
sw $t1, 16($sp) #store pivot
sw $s0, 20($sp) #store s0
la $s0, v # s0 = address of v
sll $t0, $a1, 2 # t0 = 4*l
add $t0, $s0, $t0 # t0 = address of v[l]
lw $t1, 0($t0) # t1 = v[l], t1 = pivot
move $t2, $a0 # t2 = i, t2 is f
move $t3, $a0 # t3 = j, t3 is f
for1:
slt $t4, $t3, $a1 #if(j<l) t4=1
beq $t4, $zero, end1 #goto end1 if t4 = 0
sll $t4, $a0, 2 # t4 = 4*j
add $t4, $s0, $t4 #t4 = address of v[j]
lw $t5, 0($t4) #t5 = v[j]
slt $t6, $t5, $t1 # if (v[j] < pivot) t6=1 else t6=0
bne $t6, $zero, else
move $a0, $t2 #a0 = i
move $a1, $t3 # a1 = j
jal swap # swap(i++,j);
addi $t2, $t2,1 # i++
else:
addi $t3, 1 #j++
j for1
#here stops the for1 loop
end1: #come here when exiting the for1 loop
# a0=f & a1=l
move $a0, $t2 #a0 = i
lw $a1, 4($sp) #a1= l
jal swap
move $v0, $a0 #v0=i / return i
lw $ra, 8($sp) #restore ra
lw $s0, 20($sp) #restore s0
lw $a0, 0($sp) #restore a0
lw $a1, 4($sp) #restore a1
#lw $s1, 4($sp) #restore s1
addi $sp, $sp, 24 #restore stack
jr $ra
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,您的注册使用情况与标准通话大会不同。&nbsp;我们看不到您的分区功能的呼叫者,也没有看到
交换
函数,因此我们无法对它们发表评论。通过呼叫约定的mips,
$ s < / code>寄存器(如果一个函数使用它们中的任何一个,则必须在返回呼叫者之前保留 /还原原始值。&nbsp;相比之下,其他寄存器(
$ a
,$ t
,$ v
)不需要此类保存进一步考虑。$ s
寄存器对于保存具有函数调用的循环中的变量很有用。&nbsp;这是因为允许函数调用清除非$ s
寄存器,但必须保留$ s
寄存器。&nbsp;因此,存储在$ s
寄存器中的变量将在功能调用中幸存下来。$ s
寄存器的替代方案是堆栈内存,因为它也将在函数调用中幸存下来。&nbsp;要使用堆栈内存,我们必须存储和重新加载,这对于非循环的非重复代码是可以的,但是对于循环代码,这些负载&amp;商店代表开销。相比之下,
$ s
寄存器也存储和加载,但每个功能只有一次,而不是在函数的主体中。&nbsp;因此,如果功能的主体循环循环,则进行负载&amp;在Prologue/Epilogue中存储比负载&amp;存储功能主体内部。因此,经验法则是:如果有函数调用但没有循环,请考虑需要在呼叫函数的变量的堆栈内存。&nbsp;如果没有函数调用,则不要使用
$ s
寄存器。&nbsp;如果有循环或大量函数调用,请考虑$ s
寄存器是否需要存活函数调用的变量。您需要能够分析在函数调用中是否实时变量。&nbsp;分析是:是否在函数调用之前/存在的变量存在中持有的值,然后在该函数调用之后使用?&nbsp;如果是这样,该变量必须在函数调用中生存,因此必须使用堆栈内存或
$ s
寄存器。您正在使用
$ t
寄存器作为带有函数调用的循环中使用的变量 - 这是不正确的,可能是一个问题(我们看不到swap
,所以不能确定) 。您还保留了不值得这样的保存的序言(并在结语中恢复)登记册,这是浪费但无害的。
Yes, your register usages diverge from the standard calling convention. We don't see the caller of your partition function, nor do we see the
swap
function, so we cannot comment on them.By the MIPS calling convention,
$s
registers, if a function uses any of them, must have their original values preserved / restored before returning to the caller. By contrast, the other registers ($a
,$t
,$v
) don't require such preservation, so can be freely used without further consideration.$s
registers are useful to hold variables that are used in loops that have function calls. This is because function calls are allowed to wipe out the non-$s
registers, but must preserve the$s
registers. So, a variable stored in an$s
register will survive a function call.The alternative to
$s
registers is stack memory as that will also survive a function call. To use stack memory we must store and reload, and that is ok for non-looping non-repetitive code but for looping code those loads & stores represent overhead.By contrast,
$s
registers are also stored and loaded, but only once per function invocation, instead of in the body of the function. So if the body of the function has looping then doing a load & store in prologue/epilogue is more efficient than doing loads & stores inside the function body.So, the rule of thumb is: if there's function calls but no loops, consider stack memory for the variables that need to survive function calling. If there's no function calls, then don't use
$s
registers. if there's loops or lots of function calls, consider$s
registers for variables that need to survive function calling.You need to be able to analyze whether a variable is live across a function call. The analysis is: is the value held in a variable present/existent before a function call, and then used after that function call? If so, that variable must survive function calling, so must use either stack memory or an
$s
register.You're using
$t
registers for variables used in loops with function calling — that is incorrect and potentially a problem (we don't seeswap
so cannot say for sure).You are also preserving in prologue (and restoring in epilogue) registers that don't merit such preservation, which is wasteful but otherwise harmless.