Reputation: 1584
I'm new to assemblers, so here is a simple question:
My custom subroutines change the X
, Y
, and A
registers. They manipulate these to produce the desired results. Is it a good idea to push these values to the stack when the routine starts and restore them before RTS
?
I mean, this way I can write routines which can be called from anywhere without messing up the "state" or affecting other routines. But is it OK to use the stack this way? Or is there a better way to do this?
Upvotes: 5
Views: 1479
Reputation: 477
But is it OK to use the stack this way? Or is there a better way to do this?
Absolutely; BASIC does it all the time, as do many routines in the kernal.
But, there is no right answer to this, it comes down to at least speed, portability, and style.
If you use the stack a lot, there are some speed considerations. Your typical pha
txa
pha
tya
pha
at the start, and then the reverse (pla
tay
pla
tax
pla
) eats up 3 bytes of your stack, and adds in some cycle time due to the 2 x 5 operations
You could use zero page, but that takes away some portability between different machines; VIC-20, C64, C128, the free zero page addresses may not be the same across platforms. And your routine can't be called "more than once" without exiting first (e.g. no recursion) because if it is called while it is active, it will overwrite zero page with new values. But, you don't need to use zero page...
...because you can just create your own memory locations as part of your code:
myroutine = *
; do some stuff..
rts
mymem =*
.byt 0, 0, 0
the downside to this is that your routine can only be called "once", otherwise subsequent calls will overwrite your storage areas (e.g. no recursion allowed!!, same problem as before!)
You could write your own mini-stack
put_registers =*
sei ; turn off interrupts so we make this atomic
sty temp
ldy index
sta a_reg,y
stx x_reg,y
lda temp
sta y_reg,y
inc index
cli
rts
get_registers =*
sei ; turn off interrupts so we make this atomic
dec index
ldy index
lda y_reg,y
sta temp
lda a_reg,y
ldx x_reg,y
ldy temp
cli
rts
a_reg .buf 256
x_reg .buf 256
y_reg .buf 256
index .byt 0
temp .byt 0
This has the added benefit that you now have 3 virtual stacks (one for each of .A
, .X
, .Y
), but at a cost (not exactly a quick routine). And because we are using SEI
and CLI
, you may need to re-think this if doing it from an interrupt handler. But this also keeps the "true" stack clean and more than triples your available space.
Upvotes: 5