Self-Updating Memory Copy Exercise, 6502 ASM

Below is my own modification for copying memory to Commodore 64.

I wrote char codesand number of repeatsin the table and filled screen_ram using this procedure.

I am looking for suggestions for optimization. In this case, my priority is memory.

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
+4
source share
3 answers

The correct increment of the instruction address should be performed as follows:

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

thus, probably neglecting all the memory savings for self-modified code.

I propose a different approach, which includes self-modifying instructions only when absolutization is required, and also stores the memory variables in the instructions.

.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
+3

JMP fetchNewDataBEQ fetchNewData. INC sourceAddress BEQ end, CPX #0 ( LDX). 3 .

+3

In addition to i486 sentences, if it is data_tablelimited to 128 values ​​(including a termination of 0,0), you can save a couple of bytes (and many loops), avoiding self-modifying ones LDAand using the Y register instead.

I showed it all below. You can also save another byte (delete one INY) by placing the values data_tablein two separate tables.

Alternatively, you can use Y for indexing SCREEN_RAM, but I'm not a C64 guy ...

  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
+1
source

Source: https://habr.com/ru/post/1628130/


All Articles