简体   繁体   中英

Mips assembly, “function calls” and storing return addresses onto the stack

This is hopefully a quick question for someone who understands this. But my problem is that I have an assignment, to use selection sort with a variety of methods, and I'm trying to sort out how to use the stack for saving the return address. My problem is that I can get it to go all the way to the last load return address code block, but then I get a bad address in data/stack read, can someone point out as to where I may have messed up in saving to the stack? Thank you very much!

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

Is there a reason to use the frame pointer too? You are making the stack usage in a quite complicated way.

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

Now, you shoudl handle the stack frame either in the caller or callee to keep it clear. Both making a new frame, and removing it when done with the subroutine.

In sort you call both min and swap, and both of then change both sp and fp without restoring them.

This might shed some light...

[edit]

If you insist using frames:

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

do the deed

sp = fp
pop fp
pop ra
ret

this way you have the fp-chain, and if your stack gets corrupted, you still can return fine. You don't need to push sp, because the sp is stored in fp.

The general convention is to store on the stack whatever registers can be overwritten. So if in sort procedure you want to save $ra then you need to reserve 1 word on stack. After doing all calculations before returning from the procedure you need to restora $ra and the stack pointer:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM