我正在寻找一种经济有效的方式来访问6502表中的记录。 该表长8个字节。使用正确的Y,我可以抵消字段,但我 想要一种方法来获得下一个第0个记录。
我想过:
lda #id
adc #$08
tax ; now x = x + 8
我见过其他人使用ASL而累加器的值是一个幂 2做:
asl a
tax ; x = x * 2
如果我只有2条记录,那将是很好的,但如果我再次ASL,结果将是x = 32。 这将是一个太远的补偿。
有没有比使用ADC更好的方法?
答案 0 :(得分:4)
如果该表实际上是几个8字节的记录,我会将其存储为8个1字节的记录表,可以有效地编制索引。
即数组结构,而不是结构数组
这样做的好处是允许仅使用寄存器偏移量对256条记录进行索引,并且还可以使用不同大小的记录而不更改地址计算(因此,如果您需要5字节记录,则只需使用较少的数组,而不是改变计算方法)。
LDA ELEMENT1,Y ; This is an array of the first bytes of our record
STA $1000
LDA ELEMENT2,Y ; This is the second bytes...
STA $1001
...etc...
INY ; Just need to inc Y to access next record
由于INX
/ INY
是2周期指令,因此您不会为了更新索引而超越它。
这是我的主要建议,因为它快速而简单,但它确实意味着重新格式化您的数据。
如果这不是一个选项,您可以动态重新格式化数据,使其 (假设您将访问它足够值得花费,并且您有空间这样做,或者您可以使用各种技术,具体取决于您实际想要如何访问数据,以及性能的重要性。
如果你真的需要向索引添加任意数量,而不仅仅是增量,那么天真的方法就是:
TYA (2)
CLC (2)
ADC #amt (2)
TAY (2)
如果天真的版本需要8个周期。如果省略clear-carry,则可以在6个周期内执行此操作,如果知道已经清除了,则可以执行此操作(例如,如果执行其他循环计算,则可以执行此操作循环意味着尚未生成进位)。所以值得玩弄代码以避免设置标志。任何小于4的增量都可以通过多次递增来完成。
如果您不能保证清除进位,但是您可以在内存中为查找表腾出一页,那么您可以存储0 - >在该页面的字节中执行255并执行:
LDA table + amt, Y (4)
TAY (2)
进位标志不是由那个设置的,但是零标志是,所以如果表回绕到零,你可以检查它。
如果你必须索引一个地址,那么你可以这样做:
LDA (zeropagevector), Y
增加zeropagevector
的高字节。但是,读取需要5个周期。如果您只是在一条指令中读取记录,则可以简单地使用正常的绝对寻址,并修改指令本身的地址,从而节省一个周期。
基本上,有很多方法可以在6502中优化这种事情,但它实际上取决于您的数据究竟是什么以及您希望如何访问它。
答案 1 :(得分:1)
表指针变量需要2个字节(16位),你的数据长于256字节块。
tablePointerLo = $fa ; example zeropage value
tablePointerHi = $fb ; example zeropage value
tableAddress = $1000 ; example table address
tableLength = 100*8 ; example length
tableEnd = tableAddress + tableLength
lda #<tableAddress
sta tablePointerLo
lda #>tableAddress
sta tablePointerHi
loop02:
ldy #$00
loop01:
lda (tablePointerLo),y
sta anywhereYouWant,y
iny
cpy #$08
bne loop01
lda tablePointerLo
clc
adc #$08
sta tablePointerLo
bcc pass01
inc tablePointerHi
pass01:
; do whatever you want here with the datas
lda tablePointerLo
cmp #<tableEnd
bne loop02
lda tablePointerHi
cmp #>tableEnd
bne loop02
我没有测试代码,它可能不起作用,但你应该得到主要想法。