3

我是汇编程序的新手,所以这是一个简单的问题:

我的自定义子例程更改XYA寄存器。他们操纵这些以产生所需的结果。在例程开始时将这些值推送到堆栈并在之前恢复它们是一个好主意RTS吗?

我的意思是,这样我可以编写可以从任何地方调用的例程,而不会弄乱“状态”或影响其他例程。但是这样使用堆栈可以吗?还是有更好的方法来做到这一点?

4

1 回答 1

3

但是这样使用堆栈可以吗?还是有更好的方法来做到这一点?

绝对地; 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),但需要付出一定的代价(不完全是一个快速的例程)。而且因为我们正在使用SEIand CLI,如果从中断处理程序中执行此操作,您可能需要重新考虑这一点。但这也使“真正的”堆栈保持清洁,并使您的可用空间增加三倍以上。

于 2021-10-14T22:35:46.967 回答