9

私は今 6502 アセンブリから始めていますが、8 ビットより大きい数値を処理する必要があるループに頭を悩ませています。

具体的には、いくつかのメモリ ロケーションをループしたいと考えています。疑似 C コードでは、これを行いたい:

    // Address is a pointer to memory
    int* address = 0x44AD;
    for(x = 0; x < 21; x++){
        // Move pointer forward 40 bytes
        address += 0x28;
        // Set memory location to 0x01
        &address = 0x01;
    }

したがって、RAM$44ADに書き込みたいアドレスから始めて、前方にジャンプし、そこに書き込み、それを20回実行するまで再び前方にジャンプします(最後に書き込むアドレスは です)。$01$28$01$28$47A5

私の現在のアプローチは、書くのが面倒なループ展開です (アセンブラーを使えばもっと簡単にできると思いますが):

ldy #$01
// Start from $44AD for the first row, 
    // then increase by $28 (40 dec) for the next 20
sty $44AD
sty $44D5
sty $44FD
    [...snipped..]
sty $477D
sty $47A5

絶対アドレス指定については知っていますが (Y レジスタの代わりにアキュムレータを使用します - sta $44AD, x)、それでは 0 から 255 までの数値しか得られません。私が本当に欲しいと思うのは、次のようなものです。

       lda #$01
       ldx #$14 // 20 Dec
loop:  sta $44AD, x * $28
       dex
       bne loop

基本的には、最上位アドレスから始めてループダウンします。問題は、$14 * $28 = $320 または 800 dec であり、これは 8 ビット X レジスタに実際に格納できる量を超えていることです。

これを行うエレガントな方法はありますか?

4

2 に答える 2

10

6502 は 8 ビット プロセッサであるため、16 ビット アドレスを完全にレジスタで計算することはできません。ページ 0 を介して間接的にする必要があります。

      // set $00,$01 to $44AD + 20 * $28 = $47CD
      LDA #$CD
      STA $00
      LDA #$47
      STA $01

      LDX #20  // Loop 20 times
      LDY #0
loop: LDA #$01 // the value to store
      STA ($00),Y // store A to the address held in $00,$01
      // subtract $28 from $00,$01 (16-bit subtraction)
      SEC
      LDA $00
      SBC #$28
      STA $00
      LDA $01
      SBC #0
      STA $01
      // do it 19 more times
      DEX
      BNE loop

または、自己変更コードを使用することもできます。これは一般的に疑わしい手法ですが、6502 のような組み込みプロセッサでは非常に制限されているため一般的です。

      // set the instruction at "patch" to "STA $47CD"
      LDA #$CD
      STA patch+1
      LDA #$47
      STA patch+2

      LDX #20  // Loop 20 times
loop: LDA #$01 // the value to store
patch:STA $FFFF
      // subtract $28 from the address in "patch"
      SEC
      LDA patch+1
      SBC #$28
      STA patch+1
      LDA patch+2
      SBC #0
      STA patch+2
      // do it 19 more times
      DEX
      BNE loop
于 2014-02-05T05:32:49.090 に答える
2

1k のデータをコピーするより効率的な方法:

    ldy #0
nextvalue:
    lda address, y
    sta address, y

    lda address+$100, y
    sta address+$100, y

    lda address+$200, y
    sta address+$200, y

    lda address+$300, y
    sta address+$300, y
    iny
    bne nextvalue 

いくつかのメモ:

  • ループのオーバーヘッドが減るため、高速になります。コマンドが増えるため、より多くのスペースが必要になります。

  • 使用するアセンブラがマクロをサポートしている場合、コードが処理するブロックの数を簡単に構成可能にすることができます。

これに 100% 関係があるとは限りませんが、255 よりも長いループを作成する別の方法を次に示します。

nextblock:
    ldy #0
nextvalue:
    lda address, y
    iny
    bne nextvalue

;Insert code to be executed between each block here:

    dec numblocks
    bpl nextblock

numblocks:
    .byte 3

いくつかのメモ:

  • 今のところ、このコードは特に意味のあることは何もしていませんが、ループを "numblocks" 回実行しています。「独自のコードを追加する」:-) (多くの場合、これを sta、y アドレスをインクリメントする自己変更コードと一緒に使用します)

  • bpl は危険な場合がありますが (仕組みがわからない場合)、この場合は十分に機能します (ただし、numblocks アドレスに十分な値が含まれている場合は機能しません)。

  • 同じコードを再度実行する必要がある場合は、numblocks を再設定する必要があります。

  • numblocks を 0 ページにすることで、コードを少し速くすることができます。

  • 他の何かに必要でない場合 (よくあることですが)、メモリ位置の代わりに X レジスタを使用できます。

于 2014-05-07T18:43:13.210 に答える