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

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

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
  • 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
  • 8
    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

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

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

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

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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