自修改内存复制例程练习,6502 ASM

Exercise in self modifying memory copy routine, 6502 ASM

下面是我在Commodore 64上的内存拷贝自修改例程。

我在 table 中写了 char codesnumber of repeats,并用这个例程填充了 screen_ram。

我正在寻找优化建议。在这种情况下,我的首要任务是记忆。

memCopy:    
  sourceAddress=*+1 ; mark self modifying addrres
fetchNewData:
  lda data_table    ; read char value into A
  ldx data_table+1  ; read repeat value into x
  inc sourceAddress     
  inc sourceAddress 

  cpx #00           ; if X=0 
  beq end           ; finish copying

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -

  jmp fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00

JMP fetchNewData -> BEQ fetchNewData。将 INC sourceAddress 移到 BEQ end 之后,CPX #0LDX 之后)就没有必要了。少了 3 个字节。

除了 i486 的建议之外,如果 data_table 被限制为 128 个值(包括终止 0,0),那么您可以通过避免自修改 LDAs 并改用 Y 寄存器。

我已经在下面展示了所有内容。您还可以通过将 data_table 值放入两个单独的表中来保存另一个字节(删除一个 INY)。

或者你可以使用 Y 来索引 SCREEN_RAM,但我不是 C64 人......

  ldy #0
fetchNewData:
  lda data_table,y  ; read char value into A
  iny               ; [could remove if two tables]
  ldx data_table,y  ; read repeat value into x
  beq end           ; finish copying [x=0]
  iny

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -
  beq fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00

正确的指令地址增量应该是这样的:

address=*+1
    lda self_modifying_address
    inc address+0
    bne *+5
    inc address+1

因此可能忽略了自修改代码的所有内存节省。

我建议另一种方法,它包括仅在绝对必要的地方自修改指令地址,并且还在指令中存储内存变量。

.loop
fetch_ptr=*+1
    ldx #0
    lda filler_bytes,x ;have two tables, first contains only filler bytes,
    ldy repeat_bytes,x ;second only repeat counts
    beq .exit
    inc fetch_ptr      ;this way you save 1 increment

fill_ptr=*+1
    ldx #0
.fill
    sta SCREEN_RAM,x
    inx
    bne +
    inc .fill+2 ;only self-modify high byte of address in the instruction
+   dey
    bne .fill

    stx fill_ptr

    jmp .loop
.exit
    rts


filler_bytes !byte 1,2,3,4,5,4,3,2,1
repeat_bytes !byte 4,4,5,5,6,6,5,5,4,0