MIPS汇编:内存被另一个子例程覆盖在堆栈中

时间:2018-05-17 12:27:46

标签: assembly mips mips32

在过去的3天里,我正在完成一项任务,要求我们在MIPS中实现Quicksort算法。我们得到了这段C代码:

void swap(int v[], int k, int l) {
  int temp = v[k];
  v[k] = v[l];
  v[l] = temp;
}

int partition(int v[], int n) {
  int pivot = v[n-1];
  int i = 0;

  for (int j = 0; j < n - 1; j++) 
    if (v[j] < pivot) 
      swap(v,i++,j);

  swap(v, i, n - 1);
  return (i);
}

void qsort(int v[], int n) {

  if (n > 1) {
    int p = partition(v, n);
    qsort(v,p);
    qsort(&v[p+1],n-p-1);
  }
}       

我们被要求翻译&#39;它在MIPS中。我在MIPS中提供了partition()函数,我们必须实现其他两个函数(qsort()swap())。好吧,swap()已经过测试并正常运行,因此我尝试实施qsort()并且我需要在堆栈中存储qsort()将在其后返回的地址。完成(用于递归)。问题是,无论我做什么,无论是使用堆栈和帧指针还是​​明确尝试设置空单元格,执行partition()时,替换我的数组它的一些拥有的数据。关于解决这个问题的任何想法?

我的代码在这里(任何没有评论的东西都不是我的,忽略了printArray的跳转,因为它与代码的其余部分没有关系,所以我把它留下来了):

    .globl  v
    .data
    .align  2
v:
    .word   3
    .word   10
    .word   8
    .word   2
    .word   7
    .word   1
    .word   5
    .word   9
    .word   6
    .word   4
    .text

main:
    addiu   $sp,$sp,-40
    sw      $ra,36($sp)
    sw      $fp,32($sp)
    move    $fp,$sp
    li      $v0,10          # 0xa
    move    $s0, $v0
    sw      $v0,28($fp)
    lw      $a1,28($fp)
    la      $a0, v

    jal     printArray

    lw      $a1,28($fp)
    la      $a0, v

    jal     qsort

    la      $a0, v
    move    $a1, $s0
    jal     printArray

    move    $v0,$0
    move    $sp,$fp
    lw      $ra,36($sp)
    lw      $fp,32($sp)
    addiu   $sp,$sp,40
    jr      $ra


swap:
    move    $t0, $a0    #store the address of the first cell of the array (we need this for finding v[k]'s address)
    move    $t1, $a0    #same as above (need this for the address of v[l])
    move    $t4, $a1    #load k into t4
    sll     $t4, $t4, 2 #turn k into bytes to be offset
    add     $t0, $a0, $t4   #find the address of v[k]
    move    $t4, $a2    #load l into a1
    sll     $t4, $t4, 2 #turn l into bytes to be offset
    add     $t1, $a0, $t4   #find the address of v[l]
    lw      $t2, 0($t0)     #store the element with index k in t2 (t2: temp in the C code)
    lw      $t3, 0($t1) #store the element with index l in t3
    sw      $t2, 0($t1) #store the element with index k in the address where v[l] was
    sw      $t3, 0($t0) #store v[l] where v[k] was

    jr      $ra
    nop


partition:
    addiu   $sp,$sp,-56
    sw  $ra,44($sp)
    sw  $fp,40($sp)
    move    $fp,$sp
    sw  $a0,48($fp)
    sw  $a1,52($fp)
    lw  $v1,52($fp)
    li  $v0,1073676288          # 0x3fff0000
    ori $v0,$v0,0xffff
    addu    $v0,$v1,$v0
    sll $v0,$v0,2
    lw  $v1,48($fp)
    addu    $v0,$v1,$v0
    lw  $v0,0($v0)
    sw  $v0,36($fp)
    sw  $0,28($fp)
    sw  $0,32($fp)
    b   part_loop
    nop

part_for:
    lw  $v0,32($fp)
    sll $v0,$v0,2
    lw  $v1,48($fp)
    addu    $v0,$v1,$v0
    lw  $v1,0($v0)
    lw  $v0,36($fp)
    slt $v0,$v1,$v0
    beq $v0,$0,part_noswap
    nop

    lw  $v0,28($fp)
    addiu   $v1,$v0,1
    sw  $v1,28($fp)
    lw  $a2,32($fp)
    move    $a1,$v0
    lw  $a0,48($fp)

    jal swap

part_noswap:
    lw  $v0,32($fp)
    addiu   $v0,$v0,1
    sw  $v0,32($fp)
part_loop:
    lw  $v0,52($fp)
    addiu   $v1,$v0,-1
    lw  $v0,32($fp)
    slt $v0,$v0,$v1
    bne $v0,$0,part_for
    nop

    lw  $v0,52($fp)
    addiu   $v0,$v0,-1
    move    $a2,$v0
    lw  $a1,28($fp)
    lw  $a0,48($fp)
    jal swap

    lw  $v0,28($fp)
    move    $sp,$fp
    lw  $ra,44($sp)
    lw  $fp,40($sp)
    addiu   $sp,$sp,56
    jr  $ra


qsort:
    move    $t5, $ra    #store temporarily the ret.addr. of qsort's caller
    jal     RetAddrMng  #then store it on the stack
    addi    $t6, $t6, 1 #add 1 to t6, which counts the number of times qsort has been called
    bgt     $a1, 1, sort    #sorting will continue if n > 1

sort:
    jal     partition
    move    $a1, $v0        #move 'p' from result to be the argument of the next qsort
    jal     qsort
    jr      $ra

RetAddrMng:
    sll     $t6, $t6, 2 #turn the number of times into offset bytes by quadrupling them
    add     $sp, $sp, $t6   #move the stack pointer 4*<number of times> bytes to find the next cell
    sw      $t5, 0($sp) #store the address in t5 into the stack
    srl     $t6, $t6, 2 #we will need again the number of times, so we invert the transformation by dividing with 4
    jr      $ra     #continue with qsort 

仅供参考,我正在使用MARS 4.5。

提前致谢。

0 个答案:

没有答案