Negating a number

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Negating a number
by on (#112092)
So I found this code on the wiki and it seems to work:

Code:
; 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:
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?
Re: Negating a number
by on (#112094)
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.
Re: Negating a number
by on (#112095)
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
Re: Negating a number
by on (#112096)
By the way, does SBC do A←A+C-argument, or A←A-C-argument?
Re: Negating a number
by on (#112097)
The latter.
Re: Negating a number
by on (#112100)
Quote:
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
Quote:
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.
Re: Negating a number
by on (#112101)
According to wikipedia,

Quote:
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.
Re: Negating a number
by on (#112104)
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.
Re: Negating a number
by on (#112107)
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.
Re: Negating a number
by on (#112110)
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. :-)