Marcos Moutta Posted September 5, 2020 Share Posted September 5, 2020 (edited) What I know so far - The SBC is, to make things simple, the opposite to ADC, it removes from the accumulator either a specified value or a value at some point in memory. Now, not only do I not know if that is correct, I also can't seem to use SBC propperly, for if I write SBC#$01, and the accumulator is currently $89, it becomes $87, and not $88. What's going on? Thanks! (sorry for bad english) Edited September 5, 2020 by Marcos Moutta mixed up # and $ Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 5, 2020 Share Posted September 5, 2020 2 hours ago, Marcos Moutta said: What I know so far - The SBC is, to make things simple, the opposite to ADC, it removes from the accumulator either a specified value or a value at some point in memory. Now, not only do I not know if that is correct, I also can't seem to use SBC propperly, for if I write SBC#$01, and the accumulator is currently $89, it becomes $87, and not $88. What's going on? Thanks! (sorry for bad english) Both ADC and SBC use the carry flag, except with opposite value. So, for SBC you generally have the carry flag set first (SEC) SEC LDA #$89 SBC #1 The above will give you the result you expect. However, be aware that the 6502 (in general, but not the 6507) also rely on the decimal flag for correct operation of adc/sbc operations. Usually the decimal flag is cleared at the start of every 6502 program so that ADC/SBC are operating in binary as expected. Finally - why have the carry flag at all? It's so you can do bigger than 8-bit subtracts and adds... sec lda #<$5000 sbc #<$1500 sta result lda $>$5000 sbc $>$1500 sta result+1 in the above, I did a 16 bit subtraction of $5000 - $1500 In the second part (the high bytes) I did not SEC again - because what i wanted was the "carry" result from the first one. It's an overflow of sorts, that affects if we take off an extra one when doing the high bytes. Hope this makes sense. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 5, 2020 Share Posted September 5, 2020 For ADC you have CLC to clear the carry flag, used before additions Quote Link to comment Share on other sites More sharing options...
Marcos Moutta Posted September 5, 2020 Author Share Posted September 5, 2020 3 minutes ago, Andrew Davie said: Both ADC and SBC use the carry flag, except with opposite value. So, for SBC you generally have the carry flag set first (SEC) SEC LDA #$89 SBC #1 The above will give you the result you expect. However, be aware that the 6502 (in general, but not the 6507) also rely on the decimal flag for correct operation of adc/sbc operations. Usually the decimal flag is cleared at the start of every 6502 program so that ADC/SBC are operating in binary as expected. Finally - why have the carry flag at all? It's so you can do bigger than 8-bit subtracts and adds... sec lda #<$5000 sbc #<$1500 sta result lda $>$5000 sbc $>$1500 sta result+1 in the above, I did a 16 bit subtraction of $5000 - $1500 In the second part (the high bytes) I did not SEC again - because what i wanted was the "carry" result from the first one. It's an overflow of sorts, that affects if we take off an extra one when doing the high bytes. Hope this makes sense. So as long as I don't perform any operations that go beyond FF, I don't have to set the carry flag back? Also, what happens to the carry flag if I perform more than one of those? Finally, why are the commands different for ADC and SBC if the flag is the same? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 5, 2020 Share Posted September 5, 2020 Just now, Marcos Moutta said: So as long as I don't perform any operations that go beyond FF, I don't have to set the carry flag back? Also, what happens to the carry flag if I perform more than one of those? Finally, why are the commands different for ADC and SBC if the flag is the same? You should *always* clear the carry before an addition, and *always* set it before a subtraction. Sometimes, you do know for sure what the carry flag value is, and can safely rely on that without doing a SEC or CLC before subtraction/addition. But it can be risky to do if your assumption changes without you realising. Generally, set it or clear it always. They require different values (SEC/CLC) of the carry flag, because that's how binary arithmetic works, basically. When with an add, if we get an overflow over $FF, then the carry flag is changed to set - and this gives us the +1 for the next higher byte automatically. Similarly, when with a subtract, if we get an "underflow" we get the carry flag cleared and this gives us the -1 for the next higher byte automaticlaly. clc lda valLO adc #1 sta valLO lda valHI adc #0 sta valHI In the above I show adding +1 to a 16-byte "variable" which is in two 8-bit parts, valLO and valHI In fact, the "normal" way to do this is to define just "VAL" as 2 bytes long, and do this... clc lda val adc #1 sta val lda val+1 adc #0 sta val+1 I didn't write it like that in the first example, as I didn't want you to get confused as to what "val+1" meant. It's NOT adding one to val. It's referencing the high byte in the 2-byte-long "val" variable. In other words, the "adc #1" is doing addition. The "lda val+1" is just referencing a memory location and doesn't do any addition at all. That's just for helping the assembler know which memory address you're referencing. Quote Link to comment Share on other sites More sharing options...
zbyti Posted September 5, 2020 Share Posted September 5, 2020 (edited) 47 minutes ago, Marcos Moutta said: So as long as I don't perform any operations that go beyond FF, I don't have to set the carry flag back? Py65 Monitor PC AC XR YR SP NV-BDIZC 6502: 0000 00 00 00 ff 00110000 .a 1000 $1000 a9 01 LDA #$01 $1002 c9 00 CMP #$00 $1004 b0 1a BCS $1020 $1006 PC AC XR YR SP NV-BDIZC 6502: 0000 00 00 00 ff 00110000 .a 1020 $1020 69 01 ADC #$01 $1022 8d 00 20 STA $2000 $1025 PC AC XR YR SP NV-BDIZC 6502: 0000 00 00 00 ff 00110000 .g 1000 PC AC XR YR SP NV-BDIZC 6502: 1025 03 00 00 ff 00110000 .m 2000 2000: 03 You must set or clear carry to be sure Edited September 5, 2020 by zbyti CMP & Carry Flag Quote Link to comment Share on other sites More sharing options...
zbyti Posted September 5, 2020 Share Posted September 5, 2020 (edited) Quote The CMP, CPX, and CPY instructions are used for comparisons as their mnemonics suggest. The way they work is that they perform a subtraction. In fact, CMP NUM is very similar to: SEC SBC NUM Both affect the N, Z, and C flags in exactly the same way. However, unlike SBC, (a) the CMP subtraction is not affected by the D (decimal) flag, (b) the accumulator is not affected by a CMP, and (c) the V flag is not affected by a CMP. A useful property of CMP is that it performs an equality comparison and an unsigned comparison. After a CMP, the Z flag contains the equality comparison result and the C flag contains the unsigned comparison result, specifically: If the Z flag is 0, then A <> NUM and BNE will branch If the Z flag is 1, then A = NUM and BEQ will branch If the C flag is 0, then A (unsigned) < NUM (unsigned) and BCC will branch If the C flag is 1, then A (unsigned) >= NUM (unsigned) and BCS will branch In fact, many 6502 assemblers will allow BLT (Branch on Less Than) and BGE (Branch on Greater than or Equal) to be used as synonyms for BCC and BCS, respectively. The N flag contains most significant bit of the of the subtraction result. This is only occasionally useful. However, it is NOT the signed comparison result, as is sometimes claimed, as the following examples illustrate: After: LDA #$01 ; 1 (signed), 1 (unsigned) CMP #$FF ; -1 (signed), 255 (unsigned) A = $01, C = 0, N = 0 (the subtraction result is $01 - $FF = $02), and Z = 0. The comparison results are: Equality comparison: false, since $01 <> $FF Signed comparison: 1 >= -1 Unsigned comparison: 1 < 255 After: LDA #$7F ; 127 (signed), 127 (unsigned) CMP #$80 ; -128 (signed), 128 (unsigned) A = $7F, C = 0, N = 1 (the subtraction result is $7F - $80 = $FF), and Z = 0. The comparison results are: Equality comparison: false, since $7F <> $80 Signed comparison: 127 >= -128 Unsigned comparison: 127 < 128 Notice that in both cases the signed comparison result is the same (the first number is greater than or equal to the second), but the N flag is different. The CPX and CPY instructions are exactly like the CMP instruction, except that they use the X and Y registers, respectively, instead of the accumulator. http://www.6502.org/tutorials/compare_beyond.html Edited September 5, 2020 by zbyti link Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.