7

I am currently playing around with pointer and indirect addressing on the C64 and I encountered a problem with the ADC opcode.

I am trying to increment a number repeatedly and when it overflows (goes over #$FF/255) it should increments another value by one.
But instead of setting the overflow flag after #$FF (255), the CPU sets it after #$7F (127).

After a bit of research I noticed that the ADC opcode seems to be working with signed bytes and therefore sets the C and V flags when it goes over #$7F.

Is there a way to make an unsigned addition on the 6502 by setting or clearing some flags before doing an addition or is there a trick to circumvent it ?


Here is the code I used:

PRT_LOW = $FD
PTR_HIGH = $FE
* = $1000

start
    lda #$28       ; Load value, add with carry and store the result
    adc PTR_LOW
    sta PRT_LOW
    bvc end        ; Branch on overflow clear, the V flag is set if A >= #$80
                   ;  instead of a "regular" overflow (more than #$FF)
    inc PTR_HIGH   ; Increase the "higher address value"

end
    ;[Unrelated code...]
    jmp start
1
  • You are mistaken about when the carry flag is set. The carry flag is set when the result of an addition is greater than $FF.
    – JeremyP
    Jan 2, 2018 at 10:20

2 Answers 2

22

First, you need to clear carry before doing an ADC to avoide that a random value of Carry is added.

Second, since your numbers are unsigned, Carry is what you're looking for, not Overflow. When adding a Carry is produced every time a result does not fit in a single byte. Overflow is only needed when doing signed numbers.

What you want to do should look more like this:

ADD8TO16:
        CLC     
        LDA PTR_LOW  * (*1)
        ADC #40      * Using decimal for line length is more readable, isn't it (*2)
        STA PTR_LOW
        BCC NOINC
        INC PTR_HIGH
NOINC:
        ...

*1 - Don't load constants and add pointers, load pointers and add constants. PTR = PTR + 40

*2 - But using an equate like LINELEN EQU 40 would make a real killing :))

Ok, I know, I'm a total nerd when it comes to creating readable assembly code :))


Addendum:

Now, if you realy want to dig deeper into the myteries of the overflow flag, there's a real in depth explaination on 6502.org. But be aware, it's rather complex, and unless you want to do signed arithmetics, it's better ignored:)

1
  • 1
    Ok, I know, I'm a total nerd when it comes to creating readable assembly code :)) you have to, if you want yourself (and even more others) to be able to read and understand that code 2 weeks later ;)
    – Tommylee2k
    Jan 9 at 10:14
9

Use the carry flag, not the overflow flag.

Carry dictates whether a 0 or 1 should carry over into the next column.

Overflow dictates whether the result has an unexpected sign.

If you add two positive numbers but the result is negative, that's overflow. If you add two negative numbers but the result is positive, that's overflow. There is no way to add two numbers of different signs and get the wrong result.

If you're not treating your numbers as signed then you can just ignore the overflow flag. It doesn't affect the arithmetic result, or any future arithmetic result.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .