Google-apper
Hovedmeny

Post a Comment On: Ken Shirriff's blog

"The 6502 overflow flag explained mathematically"

17 Comments -

1 – 17 of 17
Anonymous Anonymous said...

Excellent description!

January 19, 2013 at 7:01 AM

Anonymous Anonymous said...

Excellent indeed !!! ...
Complete and short

January 20, 2013 at 1:41 PM

Anonymous Anonymous said...

Thank you for the very informative article. I referenced it trying to figure out a problem in my emulator. One note that might be helpful to others is that in the "Formulas for the overflow flag" section it wasn't completely clear to me that in the "(M^result) & (N^result) & 0x80" formula, the N is ones-complement of the target, not the target. It took several readings and much comprehension to give that a try.

May 23, 2013 at 7:45 PM

Blogger Unknown said...

Writing a 6502 emulator. Was stuck on status flags for SBC and ADC. This was very helpful!

June 6, 2014 at 11:30 AM

Blogger Ken Shirriff said...

Hi Bob! 0-1 should not set overflow, since -1 fits in a byte. I didn't make it super-clear in my article, but for subtraction you need to take the ones-complement of the second value before using the overflow formulas (which are designed for addition). I.e. you're converting the subtraction to addition like in your ADC example.

Hopefully this makes things more clear. If it doesn't, let me know :-)

October 6, 2014 at 9:36 PM

Anonymous Bob Burns said...

Hi Ken. Thanks! That makes sense. Thanks for the great article.

Bob

October 7, 2014 at 4:33 AM

Anonymous Paulo said...

In the case of the SBC, shouldn't we be using the TWOS complement of N and perform an ADC, instead of ONES complement???

November 16, 2014 at 4:41 PM

Anonymous Bayle Shanks said...

Great article, thanks. I was wondering, in the two figures with columns "Inputs Outputs Example", the sixth rows say "...unsigned overflow..." whereas all of the other rows say "signed overflow". Is this a mistake, and if not, why is it "unsigned overflow" in that particular case?

September 20, 2016 at 5:13 PM

Blogger Ken Shirriff said...

Paulo: SBC takes the ones complement and adds the carry. If the carry is 1, this is the same as the twos complement. If the carry is 0, this is the same as twos complement with borrow. The tricky part here is the carry is used as an inverted borrow flag.

Bayle: you're right; that's a typo.

September 21, 2016 at 8:01 AM

Anonymous Anonymous said...

Nice.

And please note that the overflow bit can be set externally using the "SO" (Set Overflow) pin of the 6502 CPU and several of the variants.

November 21, 2016 at 6:37 AM

Blogger Zuoliu Ding said...

This detailed explanation is very helpful to understand the overflow flag generally, including other processors.

Thanks for mentioning this simple formula nicely:
V = C6 xor C7

that would be for Intel x86 processor to implement the Overflow Flag as
OF = (carry out of the MSB) XOR (carry into the MSB)

although the 6502 CPU use another implementation here. Really enjoy reading this article, concise, understandable, and straightforward.

September 7, 2018 at 9:57 PM

Blogger Lori said...

This was exceptionally useful! I have used this article a few times to reference overflow stuff. The truth tables are especially useful! A little late here, but worth noting, some of the hex results from your truth tables have the wrong values.

It's also worth pointing out, you can work out C6 with the following:

C6 = S7 xor M7 xor N7

This lets you use C6 xor C7, which works for both ADC and SBC.

In C++ that ends up looking something like:
auto c6 = ((result >> 7) & 1) ^ ((left >> 7) & 1) ^ ((right >> 7) & 1);
auto c7 = c6 ^ ((result >> 8) & 1);

I'm a little confused by what Zuolio said though, as C6 xor C7 seems to pass my 6502 conformance tests without issue. I may be missing something though!

December 15, 2021 at 1:26 PM

Blogger Zuoliu Ding said...

As from https://en.wikipedia.org/wiki/Overflow_flag, see "Internally, the overflow flag is usually generated by an exclusive or of the internal carry into and out of the sign bit."

December 31, 2021 at 2:23 PM

Anonymous Anonymous said...

Nice write-up, thanks. The tables came in especially handy for verifying my implementation of the equivalent Zilog z80 instructions.

I feel what adds to the confusion is C's implicit type promotions. It's very easy to introduce subtle bugs through them.

January 4, 2022 at 2:19 PM

Blogger robus said...

Thanks for this helpful write up, but I'll admit confusion over the Subtract handling. In order to get the calculation to work Carry in must be set? For example: If the accumulator has 0x50 and I want to subtract 0xF0, the algorithm states that we ones-compliment 0xF0 reulting in 0x0F and then call ADC - giving a result of 0x5F, not 0x60 as expected. What sets the carry flag to avoid this?

August 20, 2022 at 7:15 PM

Blogger DarioG said...

thanks Zuoliu Ding, finally found a nice and clean working tip :)

_f.CCR.Ovf = !!res3.b.h != !!((res3.b.l & 0x80) ^ (res1.b.l & 0x80) ^ (res2.b.l & 0x80));

December 30, 2022 at 3:40 PM

Blogger Professor Sockpuppet said...

@robus You would set the carry flag before calling SBC in that case, as it should be the complement of borrow. You're starting a new subtraction, therefore you've got no borrow to start with, which means carry should be set (to 1). A good example would be subtracting the same number from itself. If you add the one's complement of the same number, the result is all 1s (0xff). As this was a new subtraction, borrow should be 0, so carry should be set to 1 before the SBC. The result of the ADC with the one's complement results in a 1 in carry, meaning borrow = 0, which is correct when you're subtracting N - N. I know this seems unintuitive, I'm not sure how to explain it better :)

January 8, 2023 at 3:57 AM

You can use some HTML tags, such as <b>, <i>, <a>

Comment moderation has been enabled. All comments must be approved by the blog author.

You will be asked to sign in after submitting your comment.
Please prove you're not a robot