use*_*996 4 assembly c64 6502 calling-convention
我是汇编程序新手,所以这是一个简单的问题:
我的自定义子例程更改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
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是你的例程只能被调用“一次”,否则后续调用将覆盖你的存储区域(例如不允许递归!!,与之前相同的问题!)
您可以编写自己的迷你堆栈
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
Run Code Online (Sandbox Code Playgroud)
这还有一个额外的好处,即您现在拥有 3 个虚拟堆栈( 、 、 各一个.A).X,.Y但需要付出一定的代价(不完全是一个快速例程)。因为我们使用的是SEIand CLI,所以如果从中断处理程序中执行此操作,您可能需要重新考虑这一点。但这也可以保持“真正的”堆栈干净,并使可用空间增加三倍以上。