我是汇编程序的新手,所以这是一个简单的问题:
我的自定义子例程更改X
、Y
和A
寄存器。他们操纵这些以产生所需的结果。在例程开始时将这些值推送到堆栈并在之前恢复它们是一个好主意RTS
吗?
我的意思是,这样我可以编写可以从任何地方调用的例程,而不会弄乱“状态”或影响其他例程。但是这样使用堆栈可以吗?还是有更好的方法来做到这一点?
我是汇编程序的新手,所以这是一个简单的问题:
我的自定义子例程更改X
、Y
和A
寄存器。他们操纵这些以产生所需的结果。在例程开始时将这些值推送到堆栈并在之前恢复它们是一个好主意RTS
吗?
我的意思是,这样我可以编写可以从任何地方调用的例程,而不会弄乱“状态”或影响其他例程。但是这样使用堆栈可以吗?还是有更好的方法来做到这一点?
但是这样使用堆栈可以吗?还是有更好的方法来做到这一点?
绝对地; BASIC 一直都在这样做,内核中的许多例程也是如此。
但是,对此没有正确的答案,它至少归结为速度、便携性和风格。
如果您经常使用堆栈,则有一些速度方面的考虑。一开始是典型pha
txa
pha
tya
pha
的,然后反向 ( pla
tay
pla
tax
pla
) 占用了堆栈的 3 个字节,并且由于 2 x 5 操作而增加了一些周期时间
您可以使用零页,但这会带走不同机器之间的一些可移植性;VIC-20、C64、C128,跨平台的空闲零页地址可能不一样。并且您的例程不能在不先退出的情况下“多次”调用(例如,没有递归),因为如果在它处于活动状态时调用它,它将用新值覆盖零页。但是,你不需要使用零页......
...因为您可以创建自己的内存位置作为代码的一部分:
myroutine = *
; do some stuff..
rts
mymem =*
.byt 0, 0, 0
这样做的缺点是您的例程只能被调用“一次”,否则后续调用将覆盖您的存储区域(例如不允许递归!!,与以前相同的问题!)
你可以编写自己的迷你堆栈
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
这还有一个额外的好处,即您现在拥有 3 个虚拟堆栈(每个堆栈一个.A
, .X
, .Y
),但需要付出一定的代价(不完全是一个快速的例程)。而且因为我们正在使用SEI
and CLI
,如果从中断处理程序中执行此操作,您可能需要重新考虑这一点。但这也使“真正的”堆栈保持清洁,并使您的可用空间增加三倍以上。