Negating a number

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Negating a number

Post by Dafydd » Mon May 13, 2013 1:46 pm

So I found this code on the wiki and it seems to work:

Code: Select all

; A = -A
eor #$FF
sec
adc #0
but two's complement is normally inverting all the bits and then adding 1, so that e.g. $00 = $FF + $01 = $00 (where the addition, in this case, results in the carry flag being set).

However

Code: Select all

lda #$00
eor #$FF
adc #$01
does not seem to yield a = 0.

What am I missing about the carry flag and why would it make a difference whether it's set before the adc instruction in the first code example? And why add with 0 instead of with 1?

lidnariq
Posts: 9690
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Negating a number

Post by lidnariq » Mon May 13, 2013 2:02 pm

Since neither LDA nor EOR affect the C flag, you should end up with 0 or 1 in A, corresponding to whether C was set before you started.

ADC always does A←A+C+argument.

It doesn't matter whether the +1 in the correction after the EOR comes from #immediate or from C.

User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Negating a number

Post by Dafydd » Mon May 13, 2013 2:18 pm

Wait - the contents of C are added to A when doing ADC? :shock: ... wow. This changes things. Thanks for clearing that up.

How could I not know this already

User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Negating a number

Post by Dafydd » Mon May 13, 2013 2:33 pm

By the way, does SBC do A←A+C-argument, or A←A-C-argument?

lidnariq
Posts: 9690
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Negating a number

Post by lidnariq » Mon May 13, 2013 2:36 pm

The latter.

User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Negating a number

Post by Dafydd » Mon May 13, 2013 2:48 pm

Actually that's what the C stands for in ADC: ADd with Carry.
Yeah, but I thought that only meant that it would set Carry upon overflow (whyever I would think that, and however useful that might be), as opposed to ADD which would only... add. I don't think I've ever seen it explained anywhere what it means to Add with Carry and that it would do A←A+C+argument.

Look at this page, for example: http://www.6502.buss.hk/6502-instruction-set/adc
ADC #10 | Perform the ADC operation between $10 (Decimal 16) and the content of the Accumulator
... which does not mention Carry, and as far as I know, the Carry flag is not part of the content of the Accumulator.

Anyway, thanks to you, I know how it works now. So thanks again.

User avatar
Dafydd
Posts: 114
Joined: Sun Mar 16, 2008 1:45 am
Location: Uppsala, Sweden

Re: Negating a number

Post by Dafydd » Mon May 13, 2013 3:37 pm

According to wikipedia,
subtract with carry computes a+not(b)+C
and since not(b) = (-b-1) = -(b+1), this should mean that SBC does A←A+C-(argument+1), or A←A+C-1-argument. So that's why the Carry flag needs to be set before subtractions.

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Negating a number

Post by blargg » Mon May 13, 2013 6:29 pm

SBC is more like add carry and one's complement of operand to A. Thus you set carry to have it add two's complement to A (and clear carry to do a borrow). It's all so elegant.

BTW, a way of intuitively grasping negation is that you first flip all the bits, which is equivalent to subtracting the value from $FF. But you want it subtracted from $100, which is one more, so you add one.

User avatar
tokumaru
Posts: 11864
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Negating a number

Post by tokumaru » Mon May 13, 2013 7:35 pm

Dafydd wrote:this should mean that SBC does A←A+C-(argument+1), or A←A+C-1-argument. So that's why the Carry flag needs to be set before subtractions.
In subtractions, I like to think of the carry flag as value you put there (i.e. SEC) to be borrowed. If it doesn't need to be borrowed (i.e. no underflow) it will remain there, otherwise it will be borrowed and the carry will be clear after the operation, indicating that the next SBC must borrow 1 from the next place. I know this is not the actual logic within the CPU, but conceptually this works fine.

User avatar
koitsu
Posts: 4218
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Negating a number

Post by koitsu » Mon May 13, 2013 11:09 pm

tokumaru wrote:
Dafydd wrote:this should mean that SBC does A←A+C-(argument+1), or A←A+C-1-argument. So that's why the Carry flag needs to be set before subtractions.
In subtractions, I like to think of the carry flag as value you put there (i.e. SEC) to be borrowed. If it doesn't need to be borrowed (i.e. no underflow) it will remain there, otherwise it will be borrowed and the carry will be clear after the operation, indicating that the next SBC must borrow 1 from the next place. I know this is not the actual logic within the CPU, but conceptually this works fine.
FWIW, this is exactly how I conceptualise it as well. :-)

Post Reply