assembly 6502码中高效的多重间接寻址

brvekthn  于 2023-02-08  发布在  其他
关注(0)|答案(1)|浏览(133)

问题

我正在看一个6502程序,它有多个字节数组(音效数据对应于一个特定的声音),这些字节的长度是变化的。目前这涉及到显式地迭代第一个(如果排队),然后第二个等等,每个声音都有一个单独的变量集,用于音量,延迟等,所以代码被设置为使用这些硬编码标签。
我想把这个放进一个循环中,索引到这些额外的变量和音效数据中,索引到变量中是相当简单的,使用索引寻址,但是索引到音效数据中涉及到更多的工作,我想知道,在索引间接和间接索引寻址的应用中,我是否遗漏了一些东西。
下面是我正在做的一个独立的例子,如果可能的话,我想加强的部分是LoadFromTable中的代码,理想情况下同时使用XY寻址:

.equ  Ptr0,  0x80
  .equ  Ptr1,  0x81

  .org  0xFE00

  .org  0x0000

Init:
  LDX #0xFF
  TXS

Main:
  LDX #0x00
  LDY #0x00
  JSR LoadFromTable
  ; A should be 'H',  0x48

  LDX #0x01
  LDY #0x00
  JSR LoadFromTable
  ; A should be 'B',  0x42

  LDX #0x02
  LDY #0x02
  JSR LoadFromTable
  ; A should be 'A',  0x41

  JMP Main

LoadFromTable:
  TXA           ; Double outer index to account for 16 bit pointers
  ASL           ;   "
  TAX           ;   "
  LDA Table,X   ; Load the low byte of the array into a pointer
  STA Ptr0      ;   "
  INX           ; Load the high byte of the array into the pointer
  LDA Table,X   ;   "
  STA Ptr1      ;   "
  LDA (Ptr0),Y  ; Load the character at the inner index into the array
  RTS

  .org  0x0040

Table:
  .word Item0
  .word Item1
  .word Item2

  .org  0x0080

Item0:
  .byte 'H', 'E', 'L', 'L', 'O', 0x00

Item1:
  .byte 'B', 'O', 'N', 'J', 'O', 'U', 'R', 0x00

Item2:
  .byte 'C', 'I', 'A', 'O', 0x00

  .org  0x00FA

  .word Init
  .word Init
  .word Init

实施

接受@NickWestgate的拆分表思想,并如@Michael所指出的那样提升初始指针计算,我已经从这样的东西:

PROCESS_MUSIC:
  ; ...
  BNE   MusDoB

MusChanA:
  ; ...
  LDA   MUSICA,X
  BNE   MusCmdToneA
  ; ...
  JMP   MusChanA

MusCmdToneA:
  ; ...
  BNE   MusNoteA
  ; ...

MusNoteA:
  ; ...
  LDA   MUSICA,X
  ; ...

MusDoB:
  ; ...
  BNE   MusDoDone

MusChanB:
  ; ...
  LDA   MUSICB,X
  BNE   MusCmdToneB
  ; ...
  JMP   MusChanB

MusCmdToneB:
  ; ...
  BNE   MusNoteB
  ; ...

MusNoteB:
  ; ...

MusDoDone:
  RTS

到这个更通用的子程序:

PROCESS_MUSIC:
  LDX #0x01

PerChannel:
  ; ...
  BNE EndPerChannel
  LDA MusicTableL,X
  STA tmp0
  LDA MusicTableH,X
  STA tmp1

MusChan:
  ; ...
  LDA (tmp0),Y
  BNE MusCmdTone
  ; ...
  BEQ MusChan

MusCmdTone:
  ; ...
  BNE MusNote
  ; ...

MusNote:
  ; ...
  LDA (tmp0),Y
  ; ...

EndPerChannel:
  DEX 
  BPL PerChannel
  RTS

增加了以下表格:

MusicTableL:
    .byte <MUSICA
    .byte <MUSICB

MusicTableH:
    .byte >MUSICA
    .byte >MUSICB

这样就不需要我最初使用的LoadFromTable函数,而且总体上看起来更干净。

0vvn1miw

0vvn1miw1#

这里有几个想法,一个是传入一个已经加倍的索引(也就是说,如果你可以安排的话,或者它可能已经在前面的某个阶段在累加器中了)。
另一种方法是拆分地址表:

LoadFromTable:
  LDA TableL,X ; Load the low byte of the array into a pointer
  STA Ptr0      ;   "
  LDA TableH,X ; Load the high byte of the array into the pointer
  STA Ptr1      ;   "
  LDA (Ptr0),Y  ; Load the character at the inner index into the array
  RTS

TableL:
  .byte #<Item0
  .byte #<Item1
  .byte #<Item2

TableH:
  .byte #>Item0
  .byte #>Item1
  .byte #>Item2

如果你不能分割表,你可能仍然可以通过以下操作来摆脱INX:

LDA Table,X   ; Load the low byte of the array into a pointer
  STA Ptr0      ;   "
  LDA Table+1,X ; Load the high byte of the array into the pointer
  STA Ptr1      ;   "

自我修改代码可能有用。生活在第0页将是一个因素:

LDA Table,X   ; Load the low byte of the array into a pointer
  STA Load+1    ;   "
  LDA Table+1,X ; Load the high byte of the array into the pointer
  STA Load+2    ;   "
Load:
  LDA $FFFF,Y   ; Load the character at the inner index into the array

你还可以看到在存储指针时添加Y是否会节省周期,这可能取决于最常用的路径(即,它通常不会INC Ptr 2/Load+2)。

相关问题