如何计算表偏移量

时间:2013-01-09 17:57:30

标签: assembly 6502

我正在寻找一种经济有效的方式来访问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更好的方法?

2 个答案:

答案 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

我没有测试代码,它可能不起作用,但你应该得到主要想法。