我对汇编语言不太熟悉,所以这里有一个简单的问题:
我的自定义子例程会更改X
、Y
和A
寄存器。它们通过操作这些寄存器来产生期望的结果。在例程开始时将这些值推送到堆栈中并在RTS
之前还原,这样做是否明智?
我的意思是,这样我可以编写可从任何地方调用的子例程,而不会弄乱“状态”或影响其他子例程。但是这样使用堆栈是否正确?或者有更好的方法吗?
我对汇编语言不太熟悉,所以这里有一个简单的问题:
我的自定义子例程会更改X
、Y
和A
寄存器。它们通过操作这些寄存器来产生期望的结果。在例程开始时将这些值推送到堆栈中并在RTS
之前还原,这样做是否明智?
我的意思是,这样我可以编写可从任何地方调用的子例程,而不会弄乱“状态”或影响其他子例程。但是这样使用堆栈是否正确?或者有更好的方法吗?
但是这样使用堆栈可以吗?或者有更好的方法吗?
当然可以,BASIC经常这样做,内核中也有很多例程这样做。
但是,没有正确的答案,这取决于速度、可移植性和风格等因素。
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.