Page 1 of 1

Assembly: Detect when result rolls over from 255 to 0

Posted: Wed Oct 04, 2023 8:32 pm
by SparkyNZ
I have a loop for copying a block of more than 256 bytes using zero-page pointers

Code: Select all

        ;Increment src and dest pointers so we don't have to worry about Y register exceeding 255..
        lda SRC_PTR_LO ; Starts off at $22 in my case
        clc
        adc PIXEL_ROW_COUNT ; This is $60 (96) in my case, result becomes $82 (bit 7 and overflow are set after execution)

        ; increment HI if over flow bit set
        bvc inc_src_hi_ptr_done

        inc SRC_PTR_HI 
I thought (wrongly) that I could detect a rollover from 255 -> 0 using the overflow bit, but I see that the overflow bit gets set whenever bit 7 of A register is set (because +127 is exceeded).

When adding to the accumulator using ADC, how can I detect whether a zero roll-over has taken place? Would I need to test the accumulator first to see if its already negative/positive and then change the logic to see if the sign has changed after the ADC?

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Wed Oct 04, 2023 9:26 pm
by SparkyNZ
I think I was going about this the wrong way anyway. I've changed my code - now I'm checking for SRC_PTR_LO and DST_PTR_LO becoming zero instead. I'm using LDA (SRC_PTR_LO,y) but just keeping Y as zero the whole time and incrementing SRC_PTR_LO each time instead of using ADC and y as the counter.. It works..

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Thu Oct 05, 2023 1:21 am
by srowe
SparkyNZ wrote: Wed Oct 04, 2023 8:32 pm When adding to the accumulator using ADC, how can I detect whether a zero roll-over has taken place?
That's precisely what the carry bit is for, so your original code should have been

Code: Select all

bcc inc_src_hi_ptr_done
There are a number of implementations of block moves in the 6502.org code repository,

http://6502.org/source/general/memory_move.html

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Thu Oct 05, 2023 2:46 am
by Mike
SparkyNZ wrote:[...] copying a block [...]
srowe wrote:There are a number of implementations of block moves in the 6502.org code repository, [...]
That repository also specifically cares about the direction the pointers within source and target block must run:
  • when the target address is lower than the source address, the pointers are first set to the start of both blocks and incremented until all bytes have been copied,
  • when the target address is higher than the source address, the pointers are first set to the end of both blocks and decremented until all bytes have been copied.
If these conditions are not honoured and the blocks overlap, then parts of the source block will be overwritten before they have been copied.

See also: Counting "trick"/memory copy, where pixel specifically fell over the fact that INC and DEC do not affect the C flag. :wink:

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Thu Oct 05, 2023 4:37 am
by SparkyNZ
srowe wrote: Thu Oct 05, 2023 1:21 am That's precisely what the carry bit is for, so your original code should have been
Sigh.. Of course! Why didn't I see that? Thanks. I'll make a note for next time.

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Thu Oct 05, 2023 9:11 am
by chysn
SparkyNZ wrote: Wed Oct 04, 2023 8:32 pm

Code: Select all

        lda SRC_PTR_LO ; Starts off at $22 in my case
        clc
        adc PIXEL_ROW_COUNT ; This is $60 (96) in my case, result becomes $82 (bit 7 and overflow are set after execution)
Overflow is set in this case because you're adding two positive numbers, but the sign has apparently changed to negative. Basically, a single signed byte isn't long enough to hold a number that big. Since you don't care about signed arithmetic when dealing with 16-bit pointers, you don't care about the overflow flag.
I see that the overflow bit gets set whenever bit 7 of A register is set (because +127 is exceeded).
No, when an instruction sets bit 7, the Negative flag is set, which is tested with BMI (set) and BPL (clear). One useful application of the Negative flag in counters is when you want to include the zeroth index in your operation:

Code: Select all

        ldy #8
@@      lda src,y
        sta dest,y
        dey
        bpl @@
When you use Negative in a counter in this way, your starting index needs to be $80 or less, otherwise your loop ends prematurely. This takes advantage of the fact that lots of things affect Negative, while comparatively few things affect Carry. Fewer things still affect Overflow, only ADC and SBC*.

* This is a lie. There are other things that affect it, obviously CLV. Also PLP. Also--for a totally different reason--BIT. But it's basically true that Overflow is set because of signed arithmetic.

Re: Assembly: Detect when result rolls over from 255 to 0

Posted: Thu Oct 05, 2023 10:18 am
by Wilson
chysn wrote: Thu Oct 05, 2023 9:11 am CODE: SELECT ALL

ldy #8
@@ lda src,y
sta dest,y
dey
bpl @@
Although 9/10 times this will be

Code: Select all

ldy #8-1
:)

That or

Code: Select all

@@ lda src-1,y
     sta dest-1,y
     dey
     bne @@
Which has the benefit of allowing iteration for .Y values of [$80, $100). Of course, this only works with non-indirect addressing.