Why in MOS 6502 the SBC subtracts 2 instead of 1 the first time?

Asked

Viewed 61 times

6

I am trying to learn Assembly for MOS 6502 and I came across unusual behavior when testing my code on online emulator.

Code

LDA #$5 ; A=5
SBC #$1 ; A=3 mas deveria ser 4
SBC #$1 ; A=2 mas deveria ser 3
SBC #$1 ; A=1 mas deveria ser 2
SBC #$1 ; A=0 mas deveria ser 1

If I add one SEC between the 1st and 2nd line I get the expected result

Why does this happen?

1 answer

7


SBC is "Subtract with Carry".

Carry is what we call "Vai um" popularly, in a sum (or "lends one" in a subtraction).

In decimal, follows an example of Carry:

                   ₁  ← carry       ₁
      17           17               17       somando o Carry
    + 05    →    + 05       →     + 05      (o 1 que subimos) 
    ————         ————             ————     obtemos o resultado
                    2               22      correto, que é 22
                                          

In binary the logic is the same.

Important: Although I have given an example with the two decimal digits, the complexity of carry is not because of the bits of the same byte. Carry is used to pass bits from one byte to another, for example if you have 0x00 0xff and add one in 0xff, the byte goes back to 0x00 and the carry is set, for later you use the most significant byte, reaching 0x01 0x00 (and so on, if you use more than 8 bits).

Knowing what Carry is, let’s go to what happened in the code:

  • The first problem is that you don’t know how Carry was at the beginning of the operation. It may be that the processor has noted the "go one" of a previous operation.

  • The second is that even if it was zeroed, Carry is kind of counterintuitive in subtraction, because it works "upside down".

To solve, we have these two instructions:

  • CLC is "Clear Carry"
  • SEC is "Set Carry"

If it was an addition, we’d need a CLC before starting. Since it’s about subtraction, it’s the reverse, we need to "set" the Carry with the SEC before starting, thus leaving the code:

    LDA #$5 ; A=5
    SEC     ; Setamos o Carry para iniciar.
    SBC #$1 ; A=4, como esperado.
    SBC #$1 ; A=3, como esperado.
    SBC #$1 ; A=2, como esperado.
    SBC #$1 ; A=1, como esperado.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.