从C到MIPS的Quicksort-如何传递参数并维护堆栈框架的变量?

时间:2018-11-24 21:33:37

标签: c recursion parameters mips quicksort

我正在对整数数组创建Quicksort算法。我正在使用此C算法并将其转换为MIPS。但是,MIPS和递归确实非常困难。

我不确定如何将参数发送到递归调用QS中。我最近发现,可以通过将堆栈指针移动4个字节来更改调用堆栈中每个帧的$ s寄存器。这将使我能够为每个堆栈帧更改$ s寄存器,从而使每个QS帧不需要一百万个变量。

我的问题是我不太了解递归过程中如何以及何时设置和获取这些$ sx值。

1 个答案:

答案 0 :(得分:1)

通过移动堆栈指针寄存器($ sp)来实现递归。

首先,让我们了解移动堆栈指针的要点: 当您以高级语言使用递归时,基本上它的作用是将当前函数调用的状态“保存”在“堆栈存储器”中。 为此,您将必须:

  1. 保存程序的当前状态(所有变量/寄存器 您正在“功能”范围内使用),在堆栈内存中;
  2. “递归”调用该函数(这可能会修改您正在使用的所有寄存器);
  3. 该函数完成后,您必须恢复以前的状态并“释放”分配的空间。

但是除此之外,我们还必须保存$ ra的值,以跟踪上层函数结束时应该去的地方。

这是一个递归计算阶乘(n)的程序的简单示例:

.text
main:
  # Calls Fact with Input ($a0) N = 10
  li $a0, 10
  jal fact
  # prints the Output ($v0) Factorial(N)
  move $a0, $v0
  li $v0, 1
  syscall
  # exit
  li $v0, 10
  syscall

# Input: $a0 - N
# Output: $v0 - Factorial(N)
fact:
  # Fact(0) = 1
  beq $a0, 0, r_one
  # Fact(N) = N * Fact(N-1) use recursion
  # allocate 8 bytes in the stack for storing N, and $ra
  addi $sp, $sp, -8
  # stores N in the first, and $ra in the last position
  sw $a0, 4($sp)
  sw $ra, 0($sp)
  # call Fact(N-1)
  addi $a0, $a0, -1
  jal fact
  # Restore the values of N and $ra
  lw $a0, 4($sp)
  lw $ra, 0($sp)
  # Free the 8 bytes used
  addi $sp, $sp, 8
  # Set the return value to be N * Fact(N-1) and return
  mul $v0, $a0, $v0
  jr $ra
  # return 1;
  r_one:
    li $v0, 1
    jr $ra

基本上,这是实现代码时应牢记的。 请注意:

  • 堆栈指针递减;
  • 您需要分配多少个字节。在此示例中,我使用2个32位整数,总共8个字节。它将取决于您需要存储多少变量及其大小。
  • 如何使用正确的索引通过 lw sw 访问它们。另外,请注意内存对齐;
  • 这不仅适用于递归。您可以使用堆栈存储器来调用另一个使用正在使用的寄存器的函数(基本上与递归相同,只是不需要保存$ ra)。并且还存储数组,结构等。

编辑:

一些注意事项:

  • 执行此操作的正确位置是您的代码在其中调用函数(分配和保存),并在此调用之后(恢复和释放)。
  • 了解您的代码以了解需要保存(可能使用)哪些变量。