Destructive return: Difference between revisions
(added asm category) |
(linkify) |
||
Line 7: | Line 7: | ||
== How to do destructive returns == | == How to do destructive returns == | ||
You use stack tricks along with JSR/JSL and RTS/RTL. Assuming you just jumped to a routine with a JSL; JSL pushes 3 bytes to the stack which contains the return address. RTL pulls 3 bytes from the stack as a 24-bits address, then jumps to it which causes the return. However, if you pull those 3 bytes manually before using RTL, it will pull the 3 next available stack bytes, and jump to it, which causes a destructive return. | You use stack tricks along with [[JSR]]/[[JSL]] and [[RTS]]/[[RTL]]. Assuming you just jumped to a routine with a JSL; JSL pushes 3 bytes to the stack which contains the return address. RTL pulls 3 bytes from the stack as a 24-bits address, then jumps to it which causes the return. However, if you pull those 3 bytes manually before using RTL, it will pull the 3 next available stack bytes, and jump to it, which causes a destructive return. | ||
== SMW's usage == | == SMW's usage == | ||
SMW uses destructive returns in the "Execute pointers" subroutines, located at $00:86F9 and $00:871D. SMW also uses it with GetDrawInfo located in bank 1; it uses 2 PLA at $01:A3CB to return from the entire GFX subroutine of a sprite, when the sprite in question is offscreen. Same case with GetDrawInfo in bank 2, at $02:D3E7 and GetDrawInfo in bank 3, at $03:B7CF. | [[SMW]] uses destructive returns in the "Execute pointers" subroutines, located at $00:86F9 and $00:871D. SMW also uses it with GetDrawInfo located in bank 1; it uses 2 PLA at $01:A3CB to return from the entire GFX subroutine of a sprite, when the sprite in question is offscreen. Same case with GetDrawInfo in bank 2, at $02:D3E7 and GetDrawInfo in bank 3, at $03:B7CF. | ||
[[Category: ASM]] | [[Category: ASM]] |
Revision as of 04:04, 6 November 2023
A routine with a destructive return does not return to the parent routine. Instead, it returns to the parent's parent.
Example
Imagine that we have three routines: A, B and C. Routine A calls Routine B, which in turn calls Routine C. If Routine C was a normal routine, it would return to Routine B when it's finished. However, if Routine C has a destructive return, it will return directly back to Routine A when it's finished, skipping any code that might be left in Routine B.
How to do destructive returns
You use stack tricks along with JSR/JSL and RTS/RTL. Assuming you just jumped to a routine with a JSL; JSL pushes 3 bytes to the stack which contains the return address. RTL pulls 3 bytes from the stack as a 24-bits address, then jumps to it which causes the return. However, if you pull those 3 bytes manually before using RTL, it will pull the 3 next available stack bytes, and jump to it, which causes a destructive return.
SMW's usage
SMW uses destructive returns in the "Execute pointers" subroutines, located at $00:86F9 and $00:871D. SMW also uses it with GetDrawInfo located in bank 1; it uses 2 PLA at $01:A3CB to return from the entire GFX subroutine of a sprite, when the sprite in question is offscreen. Same case with GetDrawInfo in bank 2, at $02:D3E7 and GetDrawInfo in bank 3, at $03:B7CF.