Counting "trick"/memory copy

Basic and Machine Language

Moderator: Moderators

User avatar
pixel
Vic 20 Nerd
Posts: 867
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/pixel/
Location: various
Occupation: Pan–galactic shaman

Counting "trick"/memory copy

Postby pixel » Mon May 22, 2017 5:27 am

In the course of trying to hammer Pulse into unexpanded machines alongside darkatx' title screen and audio player for borays tune "No syrup" (don't miss the original recording) a false assumption got in the way: that the INC and DEC instructions would modify the carry flag. That "Oh no!" scream from Bridlington must have been heard in Denmark. But out came this counting trick which I haven't seen anywhere else yet. Anybody seeing issues with this one?

Code: Select all

.export moveram

.importzp s, d, c

.code

.proc moveram
    ldy #0
    ldx c
    sty c
    inc c+1         ; *honk!*
    cmp #0
    bne copy_backwards

copy_forwards:
l:  lda (s),y
    sta (d),y
    inc s
    beq k
n:  inc d
    beq m
q:  dex
    bne l
    dec c+1
    bne l
    rts

k:  inc s+1
    jmp n

m:  inc d+1
    jmp q

copy_backwards:
l2: lda (s),y
    sta (d),y
    dec s
    lda s
    cmp #$ff
    beq m2
n2: dec d
    lda d
    cmp #$ff
    beq j2
q2: dex
    bne l2
    dec c+1
    bne l2
    rts

m2: dec s+1
    jmp n2

j2: dec d+1
    jmp q2
.endproc                                                                                                                                                                                                                         
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose

User avatar
Mike
Herr VC
Posts: 2951
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Counting "trick"/memory copy

Postby Mike » Mon May 22, 2017 6:01 am

Usually, copy routines on the 65xx with LDA/STA (),Y modify Y with INY/DEY instead of doing a costly INC/DEC on the low-byte ZP address base. That way, the fix-up of the high-byte only needs to be done on over-/underflow of Y, simultaneously for both src and dst pointers, and doesn't require independent checks of both low-bytes on each loop iteration. Like:

Code: Select all

.loop
 LDA (src),Y
 STA (dst),Y
 INY
 BNE loop
 INC src+1
 INC dst+1
 DEX
 BNE loop

... and the loop is entered with a non-0 value of Y, if the transfer contains a non-complete page (adjusting src and dst beforehand).

Likewise for the other direction:

Code: Select all

.start
 CPY #0        /* fix-up for a single */
 BEQ skip      /* byte in the last page */
.loop
 LDA (src),Y
 STA (dst),Y
 DEY
 BNE loop
.skip
 LDA (src),Y   /* these */
 STA (dst),Y   /* three */
 DEY           /* go extra */
 DEC src+1
 DEC dst+1
 DEX
 BNE loop

... where the routine is entered with a non-255 value of Y for a non-complete page. Y=0 needs the special fix-up once at the start, otherwise errorneously a full page is copied. The high-bytes of src and dst need to be adjusted to point to the last page.

User avatar
pixel
Vic 20 Nerd
Posts: 867
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/pixel/
Location: various
Occupation: Pan–galactic shaman

Re: Counting "trick"/memory copy

Postby pixel » Mon May 22, 2017 6:30 am

Mike wrote:Usually, copy routines on the 65xx with LDA/STA (),Y modify Y with INY/DEY instead of doing a costly INC/DEC on the low-byte ZP address base. That way, the fix-up of the high-byte only needs to be done on over-/underflow of Y, simultaneously for both src and dst pointer, and doesn't require independent checks of both low-bytes on each loop iteration.

:shock: Oh, crap. How could I be THAT stupid!?!? At least it's now obvious why I'd better ask for review... an update of 'g'. Thanks, Mike!

Code: Select all

.export moveram                                                                                                                                                                                                                   

.importzp s, d, c

.code

.proc moveram
    ldy #0
    ldx c
    sty c
    inc c+1         ; <- the counting trick
    cmp #0
    bne copy_backwards

copy_forwards:
l:  lda (s),y
    sta (d),y
    iny
    beq k
q:  dex
    bne l
    dec c+1
    bne l
    rts

k:  inc s+1
    inc d+1
    jmp q

copy_backwards:
l2: lda (s),y
    sta (d),y
    dey
    cpy #$ff
    beq m2
q2: dex
    bne l2
    dec c+1
    bne l2
    rts

m2: dec s+1
    dec d+1
    jmp q2
.endproc
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose


Return to “Programming”

Who is online

Users browsing this forum: No registered users and 2 guests