JohnPublic wrote:
I'm reading through the commodore programmers manual (
http://nesdev.com/6502.txt) and it states that CPX (Compare Memory and Index X) changes the Negative, Zero, and Carry flag.
I'm a little confused how this works, espically with the carry flag (I understand the carry flag, but since nothing is being added/subtracted theres no overflow). Also, are the flags set being influenced by the value at the memory address or in X?
For example:
If X = 5 and the value at the memory address = 0:
Would no flag be set? Or is it the other way around and the Z flag would be set?
Can someone also provide an example of how the carry flag would even fall into all this? Thanks.
First off, the Z flag and C flag are independent of each other in the compare operation. Either one or the other, or both will be set on the result of the compare.
To compare something, you take the difference between A and B. So compare is a straight forward subtraction.
You can think of the C flag the same as with normal math:
Code:
(1)6
-9
-----
7
A carry
would have been needed because 9 is larger than 6. In decimal math, you carry/borrow from the next place depending on the result. In the above example, the 'ones' place would have needed a 'borrow' from the 'tens' place. On the cpu, there is no negative number. Instead, it 'wraps'. $01-$ff=$02. $10-$11=$ff
X=9, memory=6. The result is 7. This result is thrown
away and the flags are set/cleared accordingly. Which flags? The Z=0 was *cleared* because the result of the subtraction
didn't end up being 0. The C flag was *set* (C=1) because a borrow would have been needed. If a borrow was needed, then you know the number in register X is larger than in memory(or immediate or ZP - whatever the operand is).
Code:
ldx #$08
cpx #$09
;c=0, z=0
ldx #$08
cpx #$09
;c=1, z=0
ldx #$09
cpx #$09
;c=1,z=1
See that last one? You would think that C would be cleared because 9 is not larger than 9, so no borrow would have been needed. The explanation for this is a little complicated and not really necessary to understand for you to use it. It' easier just to remember that the C flag is also set if A=B or A-B=0. Looking at an example with branching makes it easy to understand.
Code:
ldx #$08
cpx #$09 ;c=0,z=0
*bcc less_than
beq equal
bcs equal_or_greater_than
ldx #$09
cpx #$08 ;c=1, z=0
bcc less_than
beq equal
*bcs equal_or_greater_than
ldx #$09
cpx #$09 ;c=1,z=1
bcc less_than
*beq equal
bcs equal_or_greater_than
The * represents which branch is taken. If you don't know your conditional branchs, BCC = branch if carry is clear, BEQ = branch if zero is set, BCS = branch if carry is set. If the condition of a corresponding flag of a conditional branch is not met, the cpu 'falls' through to the next instruction.
edit: updated.