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),我甚至需要这样做吗?除非需要遍历调用树,否则不需要堆栈帧。