Copying an array

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Copying an array
by on (#153337)
I have two arrays and I want to copy the contents of one array into the other.

The destination array is bigger than the source array.
The copy process has finished if the value $FF is found in the source array.
We declare a separate variable to save how many useful values are in the destination array now.

This is my code so far:

Code:
.segment "BSS"

  SourceArray: .res 10
  DestinationArray: .res 20
  DestinationArrayLength: .res 1

.segment "CODE"

CopyArray:

  ; Array index counter
  LDX #$00

@loop:

  ; Load next value
  LDA SourceArray, X

  ; Stop if value is $FF
  CMP #$FF
  BEQ @end

  ; Otherwise, copy the value
  STA DestinationArray, X

  ; Increment counter and repeat loop
  INX
  JMP @loop

@end:

  ; Save counter as new length variable
  STX DestinationArrayLength

  RTS

Alright, so far, so good.

Now my problem:
This code uses three global variables. But what do I have to do, so that the function works with any arrays and any length variable?
I.e. how can I pass "parameters" to the function, so that the function works like this:
Code:
void CopyArray(unsigned char *sourceArray, unsigned char *destinationArray, unsigned char &destinationArrayLength);
Re: Copying an array
by on (#153338)
Store your "parameters" as zeropage variables. Indirect indexed addressing (only works with Y register) can use 2-byte pointers in the ZP.

Code:
; zeropage
ptr1: .res 2
ptr2: .res 2
count: .res 1

; and then
:
lda (ptr1), Y
sta (ptr2), Y
iny
cpy count
bcc :-


Slightly more complicated if you want a 16 bit count, I'll leave that out for now.
Re: Copying an array
by on (#153339)
Alright, I assume I initialize the variables like this:
Code:
  LDA #<(sourceArray)
  STA ptr1
  LDA #>(sourceArray)
  STA ptr1 + 1


But what about the count variable? It looks like a plain variable, not like some pointer stuff.

So, is the intention that I declare a global count variable for this function and then, after calling the function, I just manually copy that variable back to the length variable that I actually need? Or is there a way to connect the function's variable to my own length variable?
Re: Copying an array
by on (#153345)
Yes, that's the correct way to store a 16-bit pointer on the ZP. LSB in the low byte, MSB in the high byte.

I didn't realize count was a return value from the function. Usually you want to use A,X,Y as parameters to a function unless you've got parameters that won't fit (e.g. pointers) or you otherwise want to preserve X/Y across the function call. Typically A is used first, then X and Y for both parameters or return values. ZP temporaries are a second resort.

Code:
; copies ptr1 to ptr2, stopping at $FF value
; returns length in A
.proc copy_array
   ldy #0
   :
      lda (ptr1), Y
      cmp #$FF
      beq :+
      sta (ptr2), Y
      iny
      jmp :-
   tya ; you could just say it's returned in Y, just doing this for a more "typical" example of return in A
   rts
.endproc

; the actual function call
; 1. prepare parameters
lda #<source
sta ptr1+0
lda #>source
sta ptr1+1
lda #<dest
sta ptr2+0
lda #>dest
sta ptr2+1
; 2. run subroutine
jsr copy_array
; 3. use returned values
sta my_count
Re: Copying an array
by on (#153389)
Thanks a lot. I will try this soon.