Function “Mips组件”;函数调用";以及将返回地址存储到堆栈上

Function “Mips组件”;函数调用";以及将返回地址存储到堆栈上,function,sorting,assembly,return,mips,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

对于理解这一点的人来说,这是一个快速的问题。但我的问题是,我有一个赋值,使用选择排序与各种方法,我试图排序如何使用堆栈来保存返回地址。我的问题是,我可以让它一直运行到最后一个加载返回地址代码块,但是在数据/堆栈读取中,我得到了一个错误的地址,有人能指出我在保存到堆栈中时可能出错的地方吗?多谢各位

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
main:
低于$sp,$sp,4
西南$ra,($sp)
日航分拣
j出口
互换:
低于$sp、$sp、8
sw$fp,4$sp
添加$fp、$sp、4
西南$ra,($fp)
lw$ra,($fp)
jr$ra
最小值:
低于$sp、$sp、8
sw$fp,4$sp
添加$fp、$sp、4
西南$ra,($fp)
lw$ra,($fp)
jr$ra
排序:
低于$sp、$sp、8
sw$fp,4$sp
添加$fp、$sp、4
西南$ra,($fp)
日民
日航互换

lw$ra,($fp)是否也有理由使用帧指针? 您正在以一种相当复杂的方式使用堆栈

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而不恢复它们

也许能给我们一些启示

[编辑]

如果您坚持使用框架:

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

do the deed

sp = fp
pop fp
pop ra
ret
这样,您就拥有了fp链,如果堆栈损坏,您仍然可以返回
好的您不需要推送sp,因为sp存储在fp中。

是否也有理由使用帧指针? 您正在以一种相当复杂的方式使用堆栈

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而不恢复它们

也许能给我们一些启示

[编辑]

如果您坚持使用框架:

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

do the deed

sp = fp
pop fp
pop ra
ret
这样,您就拥有了fp链,如果堆栈损坏,您仍然可以返回
好的您不需要推送sp,因为sp存储在fp中。

一般惯例是在堆栈上存储任何可以覆盖的寄存器。所以,若在排序过程中要保存
$ra
,那个么需要在堆栈上保留1个字。完成所有计算后,再从过程返回,需要恢复a
$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

一般惯例是在堆栈上存储任何可以覆盖的寄存器。所以,若在排序过程中要保存
$ra
,那个么需要在堆栈上保留1个字。完成所有计算后,再从过程返回,需要恢复a
$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

谢谢你的awnser,我只是对如何使用堆栈以及何时何地存储东西感到困惑。所以当我这样做时(添加$fp,$sp,4),我甚至需要这样做吗?除非需要遍历调用树,否则不需要堆栈帧。感谢您的awnser,我只是对如何使用堆栈以及何时何地存储东西感到困惑。所以当我这样做时(添加$fp,$sp,4),我甚至需要这样做吗?除非需要遍历调用树,否则不需要堆栈帧。