Video summary
In Part 16 of his series on building a 6502 emulator in Python, the developer focuses on implementing logic for the overflow flag, which is crucial for handling signed 8-bit arithmetic correctly. Unlike the carry flag that deals with unsigned numbers ranging from 0 to 255, the overflow flag applies to the range of -128 to +127 used by two's complement representation. The core concept explained is that an overflow occurs specifically when adding or subtracting two operands of the same sign results in a value whose sign bit flips unexpectedly; for instance, adding two positive numbers should not yield a negative result, nor should subtracting two negatives yield a positive one.
The implementation process involves modifying the existing code for the ADC (Add with Carry) and SBC (Subtract with Carry) instructions to detect these specific conditions before they wrap around. The developer writes logic that compares the sign bits of the original operands against the sign bit of the final wrapped result, setting a flag if there is a mismatch indicating an invalid mathematical outcome within the signed range. This requires careful manipulation of temporary variables to preserve the initial state of the accumulator and the operand being added or subtracted before any arithmetic operations alter their values in memory.
Throughout the coding session, the developer encounters several syntax errors and logical pitfalls while testing various scenarios with positive and negative numbers using Python's boolean logic. After initially struggling with incorrect assumptions about how specific combinations like adding 64 to another value should behave, he refines his code through iterative debugging until it correctly identifies overflow events in cases such as combining two large negative values or exceeding the maximum positive limit. Once satisfied that the detection mechanism works for addition, he copies this logic over to the subtraction routine with minor adjustments, acknowledging that while there is still one unimplemented instruction regarding bit manipulation, the core functionality for signed arithmetic errors is now operational.
Read the full video transcript
Okay, welcome to 6502 emulator in Python
part 16. We're moving right along. In
today's video, we're going to be working
on the overflow flag. Um, which is very
similar to carry, uh, which is, if you
recall when we, let's say we have 255
and, you know, it's 8 bits. So, we have
255, we add one, uh, we carry the one,
so we wrap around a zero and the carry
flag is set. or if we're at zero, we
subtract one, we wrap around 255, and we
set the carry flag. We're doing the same
thing here, but with signed 8 bit
numbers. And I'll explain that in just a
sec here. And there are two instructions
I'm going to add this code to. There's
actually a third, but I haven't
implemented that yet. So, I'm just going
to do the ones that I've already
implemented. So, add with carry and
subtract with carry. So, let's take a
look at our code first. So, you know,
previously we've been working on these
different flags. We haven't done them
all, but we've done we've done stuff
with negative. So if a number is
negative, we set the negative flag to
true. Uh we haven't done overflow yet.
We have that's what we're going to do
now. We haven't done break or decimal.
We have done interrupt. Um so we're but
we have done zero and carry in just you
know various places. So uh yeah, so
we're going to be working on the
overflow. So let's let's take a look at
what that actually is. Um, so
there's an explanation here on this page
and it talks about the the overflow flag
is generally misunderstood
and um it goes through a bunch of stuff
makes it a bit complicated to
understand. But if you recall um from a
while ago we looked at uh signed versus
unsigned uh 8bit values. So 0 through
127
are just as you would expect. Those are
the positive numbers from 0 to 127. But
because we're using this last bit here
to represent negative, so 0 is positive,
1 is negative. So 128 as an unsigned
decimal is actually -28.
Okay. So let's say that we have,
you know, - 128 and we add 127, we're
going to get -1. So we we haven't
wrapped around. We we're going to we're
not wrapping around. But if we subtract
127,
uh obviously we're going to wrap around.
Um you we subtract one, we're going to
wrap around. Um so it gets weird just
the way the the math works out. Um but
basically that's what we're looking at.
So instead of uh 0 and 255 being our
boundaries, our boundaries are going to
be -128 and 127. And there's actually an
easy way to to figure out, you know,
figure this out without actually having
to do a lot of math. And that's why it's
good that we have a second source uh
here which talks about it as well. And
so basically
explains here uh how is signed overflow
different from the carry flag and it
talks about blah blah blah blah blah
blah blah. But the important part is if
the operins are of the same sign, the
case may occur where the sign bit flips
as indicated by a change of the negative
flag while the result is still of the
same sign. Um the condition is indicated
by the overflow flag. So notably an
overflow can never occur when the
operins are of opposite signs.
Huh. So what does that actually mean? So
um to give an example here. So we load
uh 40 which is here. Now notice this is
set to positive. I should make that a
little bigger on the screen.
So
dollar is 40. This is that's 64. So this
is one. This is zero means we're looking
at positive 64. We're going to add 40.
So that flips over to here. That gives
us 1. Now, normally that would give us
128. Uh, but because we're in negative
territory now because we just switched
over to negative uh what is that? I
guess that's zero. Um,
so 1 0 0. Actually, that flips over to
-1 128 cuz I g 0 0. So the way to tell
if I understand correctly from what it's
saying
is that if this bit is zero
for this value and this bit is zero and
the result is non zero here we've
overflowed. By the same token if this is
one and this is one and this becomes
zero we've overflowed. That's my
understanding of it. Um,
so let's see if that works. Let's let's
just let's just program it that way and
hope for the best. Um, yeah, I'll have
to test out some other systems to see if
I got it right. But I think that that
makes sense. So let's go ahead and look
at the coding side of this. Now, as I
said, it only affects the add with carry
and the subtract with carry. So what I'm
going to do is I'm going to add carry.
And the thing is we need the original
value
and we need the accumulator value.
Okay.
So
that says if the carry flag is set add
one.
I'm going to assume that's afterwards.
Um okay. So this gives us a bit of a
wrap. Um so that's interesting. How do
we deal with that? Do we have to worry
about that or not? I guess we don't
because we are
just looking at the overflow thing. So,
let's go ahead and set overflow if
necessary.
And this may not be 100% correct. That's
my current understanding. That was part
of this project was to try to figure
these things out. Let's go ahead and
code it as if my understanding is
correct. So, again, we've got value and
we got self. A.
So, um
So we need to check. So we need if
uh what's that? So value
and um
128 that tells us if it's negative
um and I think this is I'm going to try
this. This is what we were told in the
previous video by Ry. He said this
should do what I won't do. So basically
I'm trying to say is the 128 bit set
which is the far left bit that tells us
if it's positive or negative. So if it's
negative and
uh bull sorry yeah bull self a wait the
value is negative
no we need the self a okay so
all right
so we get the value here so it's the
original value so I'm going have to make
a temp value temp value for overflow
overflow
checking.
Okay, so temp equals value. All right,
so if cuz here we've changed the value.
So we need to know if the temp
is negative and the
final
value.
We got to do this after wrapping. Um
that's tough. Uh let's see here.
H. Okay, let's try it. self. Wrap.
There we go. Value.
Notice we're not changing the value.
We're just getting the wrapped value. So
that that'll work.
All right.
That's
that.
H. All right. So, the first two.
Okay.
Jeez. All right. Um, I really should
have Yeah, I'm messing this one up. So
we need to know we know the original
value of a
the original value that we're adding
and the result of that ad
wrapped.
Wow.
Okay. So
temp value equals value
temp a equals self a.
All right, there we go. Cuz here we're
making some changes cuz we we calculate
the value. We've added the value to self
a.
Yeah.
And that gives us our final that's our
final value.
Okay.
So, we got two cases. So, we're going to
do pause pause neg.
We're going to do neg pause. All right,
let's try this. So, I'm doing a
different order than I did last time.
Okay. So if [sighs and gasps]
temp value and
128
bool temp value.
So if that's set that's no no
let's do neg positive that's easier. Um,
copy paste
X.
All right. Negative positive. All right.
And 128
and B temp A.
Um,
and 128. So if that's negative
and
not not
well
bool
let's try this try not bool
self wrap
self a
uh selfv equals true
because if I'm doing this right we have
a negative number a ne so the value is
negative a is negative and the result of
a is not negative
so whatever results is not negative and
then it is
not it is true that that means it's an
overflow so by the same token in we
should be able to do this if not bool
not bool
and b.
So I just do else selfv equals
false.
Does that make sense?
How about that? We'll do the we'll do
else if here. Um
like a little logic error there.
LF.
All righty. Get rid of that.
So, negative and positive.
Positive. positive and neg.
Yeah, let's try it. I'm going to see if
it compiles first.
Okay. I've been programming too much
Java lately. and and and and
all right. I'm sure there's a much more
elegant way to do this, but
um
why is that still red? Let's compile.
Invalid syntax is it just not
god. All right. If not pool
um
do a lot of Java lately. Is this going
to work
syntax?
If pool
All right, let's try this. Okay,
compile. That's a good sign. Okay, so I
already did some testing code. So, I'm
just doing that example, that exact
example. I'm taking 40 and I'm adding
carry 40. Um,
and then I got to actually No, I think
no, I don't do that. That's all I got to
do. Um, yeah, let's try it. See what
happens.
Okay, so we've got 64. Okay, notice the
overflow is not set. We're going to add
64, which is going to push it to 128,
which is going to give us that one in
the uh leftmost column. And
for heaven's sakes,
not add carry. What I do tempus self.
Okay, [sighs and gasps]
let's try this again.
All right, 64. We're going to add and
negative is set, but the overflow is not
set.
Well, that's annoying. Um,
all right, let's go back to the drawing
board.
Let's make sure
first of all this is correct. So where's
add carry
immediate 069. All right, that's a good
sign. Um
let's go back to the command.
So we have a positive positive
No temp
equals true. Ah, duh. See, Java would
have caught that. I think it just did
lowerase V. Yeah.
Selfb.
Why did I capitalize that?
I probably always capitalize the
literature. Um, makes sense. All right,
let's try it again.
Okay, 64.
Now we have 128 and the V flag is set.
Oh my gosh, I'm so happy. All right, I'm
going to try a different value here. Uh,
I just want to make sure that it doesn't
go over. So, let's try two positive.
Let's try a positive value. Um, so let's
try 40 and 20. So, that's going to give
us positive positive and it'll result in
a positive of 60. Um yeah, is that
positive? Yeah. Oh, maybe we'll find
out.
96.
No, it is positive. Okay, let's do one.
Uh
01
should consistent that there.
Okay, so we're going take 40. We're
going to add one.
So, that should just give us 41, which
is not high enough.
I'm annoyed.
I'm officially annoyed. [gasps]
Um, that should not overflow.
That should be 65.
Yeah, that's not overflow. Shouldn't
overflow.
All right, back to the drawing board.
I'm making an assumption here that this
is correct. I'm going to try and
So printing
do a little testing now. I I know I can
do debugging and set break points and
things but
um
See if this works.
All right.
False. False. False.
Then why is overflow set [laughter]
false?
All right, let's try this again.
Wait, wait, wait, wait, wait.
Yeah, the logic is completely wrong.
Okay. So,
okay. So, negative negative.
Oh, that was dumb.
And 128.
There are just days when I just feel
like I should just give up.
Do something stupid like that. All
right, let's uh go ahead and put that in
there.
All right, it's already done that. All
right, let's try this again. System.
This is why I got to test it, right?
Because we got we had a false, you know,
positive there. 64 65 no overflow. Okay,
let's go back and do
one that we know gives an overflow. 40
and
64
overflow and negative. Awesome, dude.
I'm so excited. Um,
all right, let's try two negative
values. Let's do um
well, let's do Oops. Let's do the 0x 80.
Let's do
Let's do 80 and 80. 80 and 80.
Okay. So, that should hopefully
wrap us around to zero.
So 128 128 gives us 256 which so yeah
128 is like you know negative whatever
128 I think and then 128 that wraps us
around
and we have the wrap so I think that is
working as it's supposed to. So oops
control Y.
All righty. So that is that. Um, so
basically what I can do is because it
works the same subtract. Now that I got
this working, I can just copy and paste
it over to SBC,
I believe. SBC.
Where did I put that?
Let's see here. SBC ADC. I put it
after the carry thing. Okay. So, SBC.
All right.
And I do the same thing with temp
ADC.
Getting the value. Copy.
All righty.
Compile. Yeah. All right. Let's go up to
here. Let's go back and find out what
SBC is.
E9.
I'm going to go back to here. Here I'm
going to do SBC
and it's going to give us E9.
Um the only thing is subtract is if we
subtract two negative numbers.
Yeah. Okay.
Because it can't go. Yeah. We have to go
over. Okay, that makes sense. All right.
So we got we got a negative number and a
negative number.
and
negative number and a negative number.
128
and that
doesn't overflow.
Oh, did I change that? Yeah. So, 80.
Let's go back to the example over here
and see if we can figure that out.
81.
So 81's negative 127.
Oh, let's add
um
let's see here. So he's right.
Okay, let's subtract. Okay, that was
that was good. 255 is still a negative
number. So let's subtract
01.
Crl + Z
126 which is a positive number.
Uh, let's try
F.
All right, let me think this through.
Um, let's go back to here.
128.
Is it different with subtract?
I do not know.
Let's go back to here.
I'll try again.
can never go.
Overflow may only occur if both operands
are of the same sign. There's
the same sign.
All right, I'm just going to go by what
this says and assume that I'm doing it
right. I have to think about like a prop
something something to test that because
I don't quite get the math on it to be
honest. But I am going to go ahead and
say I'm going to put this in the wing
column. It's uh video's long enough. So
anyway, uh just back to what we did. Uh
we looked at the overflow
uh flag which is again similar to carry
but relevant only to signed 8 bit
numbers. We saw some examples there.
reasonably confident this is correct and
uh
implemented only with add with carry and
subtract with carry. There's one more
command bit, but I'm not 100% sure what
it does. I've read the instructions, but
I got to read it again to be sure. So,
yeah. Uh, making some progress getting
into some of the harder nitty-gritty
stuff. So, I hope you're enjoying this.
Comment below, follow, subscribe, you
know, the whole thing. Uh, you know
what? And most importantly, keep on
coding. Take care.