Lessons I've, just, learned the hard way. I thought I'd share
them.
Moving or copying blocks of memory can be tricky with the
6502. I've made all the mistakes so I thought, I'd put them
here to, maybe, save others the pain.
A simple move, down in memory, might look like:
Code:
; ON PAGE ZERO RESERVE SOME SPACE
IXFRM DW 0 ; INDEX FROM
IXFRMH=INDXF+1
IXTO DW 0 ; INDEX TO
; sOME PLACE ELSE
SIZE = $55
FROM = $100
TO = $210
MOV1 LDX # (FROM-1)&$0FF ; depending on the assembler you might
STX IXFRM ; not need any '&$0FF' but I include it
LDX # ((FROM-1)/$100)&$0FF ; here for completeness
STX IXFRMH
LDX # (TO-1)&$0FF
STX IXTO
LDX # ((TO-1)/$100)�FF
LDY # SIZE
MOV11 LDA(IXFRM),Y
STA(IXTO),Y
DEY
BNE MOV11
All looks OK but what say you wanted to move $100.
if you do it the same, you can't set Y=$100 for the
size.
An alturnative might look like:
Code:
MOV2 LDX # FROM&$0FF
STX IXFRM
LDX # (FROM/$100)&$0FF
STX IXFRMH
LDX # TO&$0FF
STX IXTO
LDX # (TO/$100)&0FF
LDY # SIZE
MOV21 LDA(IXFRM),Y
STA(IXTO),Y
DEY
BNE MOV21
Of course, anything over $100 would need to be done
in multiple chunks of $100 or less.
There is a potential problem with MOV2. If the from
data overlaps the first byte of the to location, the
first byte of the to location is over written.
If one is making a general case of a move down, it is
safer to use blocks smaller than $100 in size. The
math is simplest for $80 in size and use MOV1 and
avoid MOV1.
An alternative that, take more, code might be:
Code:
MOV3 LDX # FROM&$0FF
STX IXFRM
LDX # (FROM/$100)&$0FF
STX IXFRMH
LDX # TO&$0FF
STX IXTO
LDX # (TO/$100)&0FF
LDY # SIZE
MOV31 DEY
BNE MOV22
LDA(IXFRM),Y
STA(IXTO),Y
JMP MOV21
MOV32
It still won't do a size of $100.
Just now learning my 6502 coding.
Dwight