Mips程序集,“函数调用”并将返回地址存储到堆栈中

时间:2013-12-06 21:41:45

标签: function sorting assembly return mips

对于理解这一点的人来说,这是一个很快的问题。但我的问题是我有一个任务,使用各种方法的选择排序,我正在尝试理清如何使用堆栈来保存返回地址。我的问题是我可以让它一直到最后一个加载返回地址代码块,但后来我在数据/堆栈读取中得到一个错误的地址,有人可以指出我可能在保存到的地方搞砸了堆栈?非常感谢你!

main:
 sub $sp, $sp, 4
 sw $ra, ($sp)
 jal sort

 j exit

swap:
 sub $sp, $sp, 8
 sw $fp, 4($sp)
 add $fp, $sp, 4
 sw $ra, ($fp)

 lw $ra, ($fp)
 jr $ra

min:
 sub $sp, $sp, 8
 sw $fp, 4($sp)
 add $fp, $sp, 4
 sw $ra, ($fp)

 lw $ra, ($fp)
 jr $ra

sort:
 sub $sp, $sp, 8
 sw $fp, 4($sp)
 add $fp, $sp, 4
 sw $ra, ($fp)

 jal min

 jal swap

 lw $ra, ($fp)        <---- Bad address in data/stack read Exception
 lw $fp, 4($fp)
 jr $ra

exit:

 li $v0, 10                 #exit
 syscall

2 个答案:

答案 0 :(得分:0)

是否有理由使用帧指针? 您正在以非常复杂的方式使用堆栈。

swap:
 sub $sp, $sp, 8 ; room for 2 words
 sw $fp, 4($sp)  ; store sp in the first
 add $fp, $sp, 4 ; fp = sp + 4 ? Why?
 sw $ra, ($fp)  ; store return address

 lw $ra, ($fp)  ; get return address - leave the fp and sp alone
 jr $ra         ; return, and leave the sp and fp unbalanced

现在,您应该在调用者或被调用者中处理堆栈帧以保持清晰。 两者都制作一个新的框架,并在完成子程序时将其删除。

在排序中你同时调用min和swap,然后两者都改变​​sp和fp而不恢复它们。

This可能会有所启发......

[编辑]

如果你坚持使用框架:

push ra
push fp
fp = sp
{ push local variables }

do the deed

sp = fp
pop fp
pop ra
ret

这样你就拥有了fp-chain,如果你的堆栈被破坏了,你仍然可以返回 精细。你不需要推sp,因为sp存储在fp。

答案 1 :(得分:0)

一般约定是在堆栈上存储任何可以覆盖的寄存器。因此,如果在排序过程中要保存$ra,则需要在堆栈上保留1个单词​​。在从程序返回之前执行所有计算之后,您需要使用restora $ra和堆栈指针:

sort:
   addi $sp, $sp, -4
   sw $ra, 0($sp)   # saves $ra on stack

   # do calculations
sort_end:
   lw $ra, 0($sp)
   addi $sp, $sp, 4
   jr $ra