8

I am trying to code in 6502 assembly and for some reason the CMP instruction doesn't work. For example:

   CLD
   LDY #$03
   LDA #$00
   LDX #$05
   CMP Y
   BEQ Equal
   STX $0200
Equal:
   BRK

This should place a green square on the screen if I am correct but it doesn't, it skips right over the STX line because apparently the equal flag is raised. I'm new to 6502 assembly so I could just be making a mistake.

  • 2
    It would help if you could also say which assembler and machine you're trying to code for. (regardless I suspect the answer that's been given is correct) – PeterI Oct 15 '18 at 17:34
  • 1
    Which 6502-based machine has screen (colour?) memory at $0200? – berendi Oct 15 '18 at 17:49
  • This is just a simple assembler/ide that I picked up from Github user skilldrick, Its not really a full machine. – user115898 Oct 15 '18 at 17:52
  • 9
    Unless Y is declared as a label somewhere (which is probably not a good label name to use, but for the sake of argument), that should not even assemble. Sounds like it's not a very mature assembler. Update: It's definitely not. Tried LDA X, STA Y at skilldrick.github.io/easy6502 and that assembles without errors (to an address operand of 0xFF 0xFF, as does any unknown labels).¯\_(ツ)_/¯ – Retrograde Oct 15 '18 at 20:30
23

The code you've posted:

  • loads the immediate value 0 into A;
  • loads the immediate value 3 into Y;
  • then compares the 0 in A to whatever is in memory at the address you've given the label Y.

There are no register-to-register comparisons on the 6502.

  • 2
    I've suffered a major memory failure here; somehow CPY had mutated into an implied operation in my head. You're right, it's not, it's exactly like CMP but for Y. So I don't think you can directly compare the two registers. – Tommy Oct 15 '18 at 17:51
12

There are no register/register operations on the 6502 (except for transfer). The 6502 follows a strict accumulator/memory scheme (with a few extensions for index-register/memory).

Your example is a bit useless, as comparing two constants doesn't make sense - one needs to be a variable at least, right? Let's assume the first (#$03) is a memory location called VALUE instead. So a useful check for VALUE holding 00 would work like this:

   LDX #$05    * Prepare X
   LDA VALUE   * Value to compare
   CMP #$00    * Compare with this
   BEQ Equal   * Do not store X when equal
   STX $0200   * Store X
Equal:
   BRK

In a real life 6502 program the CMP instruction can be left out completely, as loading a value already performs a test for zero.

(Further, CLD is not needed, as decimal mode has no influence beside addition/subtractions and there is no need to use X, as storing a constant value (or moving one) can be done by using A after the BEQ - same program length but fewer cycles when not needed. And so on :)))

  • 2
    Note, CMP also sets the carry, which an LDA doesn't, so LDA something; CMP #0 is not identical to just LDA something. – Mr Lister Oct 16 '18 at 7:10
  • 1
    @MrLister Right, except, comparing with Zero will never set carry, just clear it in case it was set before. This makes an even better point for using LDA, as mow both flags can be used to crete a rather tight code sequence. Excpet, that's maybe a few years of experiance above the level asked :)) – Raffzahn Oct 16 '18 at 7:42
  • @MrLister was right the first time: comparing with zero will always set the carry, since all values are >= zero. – peter ferrie Oct 20 '18 at 22:38
  • @peterferrie True, still the point stays the same. After a CMP with Zero the carry is in a predefined position, thus unsuable for this operation and killing any other usage as well. The best test for Zero is just watching the Zero bit after a load. – Raffzahn Oct 21 '18 at 9:00
1

If you use CMP that's the instruction to compare the accumulator A with a value which is either immediate as in CMP #$44, or from an address, such as CMP $102C,X which in this example is memory address $102C with the contents of the X register added to the address.

The best way to think about CMP is to realize it's just SBC (with carry implicitly set), that is the subtract instruction, but it doesn't save the result.

So if I have $21 in the accumulator and do a CMP #$10 then it gets the result $11 and sets the flags based on that subtraction, but then it throws away the $11 without changing anything.

So if you do a CMP #$21, then the result is zero so the zero flag is set (and the carry flag remains set). If you do CMP #$22 then the carry flag is cleared because it would need to borrow from the next byte in a subtraction, but for more specifics check out: http://6502.org/tutorials/compare_beyond.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.