1

6502 テーブルのレコードにアクセスする費用効率の高い方法を探しています。テーブルの長さは 8 バイトです。間接 Y を使用して、フィールドをオフセットできますが、次の 0 番目のレコードに到達する方法が必要です。

私は考えました:

lda #id
adc #$08
tax ; now x = x + 8

アキュムレータが 2 の累乗の値を持っている間に ASL を使用する他の人を見てきました。

asl a
tax ; x = x * 2

レコードが 2 つしかない場合はこれで問題ありませんが、もう一度 ASL を実行すると、結果は x = 32 になります。これはオフセットが大きすぎます。

これを行うには、ADC を使用するよりも良い方法はありますか?

4

2 に答える 2

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/は 2 サイクルの命令であるためINY、インデックスの更新に勝るものはありません。

データの再フォーマットを意味しますが、これは高速で簡単なので、私の主な推奨事項です。

これがオプションでない場合は、データをそのように動的に再フォーマットすることができます(コストに見合うだけの十分なアクセスがあり、そのためのスペースがあると仮定します)。実際にデータにアクセスする方法やパフォーマンスの重要性に応じて、さまざまな手法を使用できます。

インクリメントするだけでなく、任意の量をインデックスに追加する必要がある場合は、単純な方法で次のようにします。

TYA      (2)
CLC      (2)
ADC #amt (2)
TAY      (2)

ただし、その単純なバージョンには 8 サイクルかかります。クリアキャリーを省略した場合、6 サイクルで実行できます。これは、既にクリアされていることがわかっている場合に実行できます (たとえば、ループ内にあることがキャリーが実行されていないことを意味する他のループ計算に従う場合)。生成されています)。そのため、フラグを設定しないようにコードを調整する価値があります。4 ずつインクリメントするよりも小さいことは、複数回インクリメントするだけで実行できます。

キャリーがクリアされることを保証できないが、ルックアップ テーブル用にメモリ内のページを確保できる場合は、そのページのバイトに 0 -> 255 を格納して、次のようにします。

LDA table + amt, Y (4)
TAY                (2)

それによってキャリーフラグは設定されませんが、ゼロフラグは設定されるため、テーブルがゼロにラップアラウンドする場合は、それを確認できます。

アドレスをインデックス化する必要がある場合は、次のようにすることができます。

LDA (zeropagevector), Y

の上位バイトをインクリメントしますzeropagevector。ただし、読み取りには 5 サイクルかかります。単一の命令でレコードから読み取るだけの場合は、通常の絶対アドレス指定を使用して、命令自体のアドレスを変更し、サイクルを節約できます。

基本的に、6502 でこの種のものを最適化する方法はたくさんありますが、実際には、データが何であり、どのようにアクセスしたいかによって異なります。

于 2013-01-09T19:13:46.317 に答える
1

データが 256 バイト ブロックよりも長い場合、テーブル ポインター変数には 2 バイト (16 ビット) が必要です。

    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

私はコードをテストしませんでした。動作しない可能性がありますが、主なアイデアは理解できるはずです。

于 2013-01-10T08:15:29.623 に答える