分区功能的错误(MIPS组件)

发布于 2025-01-25 17:44:16 字数 1753 浏览 1 评论 0原文

这是我编写的代码,试图在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

动听の歌 2025-02-01 17:44:16

我也对存储和恢复寄存器有点困惑,也许问题在于。

是的,您的注册使用情况与标准通话大会不同。&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,所以不能确定) 。

您还保留了不值得这样的保存的序言(并在结语中恢复)登记册,这是浪费但无害的。

Also I am kind of confused about storing and restoring registers, perhaps the problem lies there.

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 see swap 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文