I have recovered an old 6502 emulator I did years ago to implement some new features. During testing I discovered something wrong, surely due to an error in my implementation.
I have to loop through a 16 bit subtraction until the result is negative: quite simple, no? Here is an example:
V1 equ $90
V2 equ $01
Label:
sec
lda V2
sbc #2
sta V2
lda V1
sbc #10
sta V1
"Branch" to Label if result is >0, otherwise exit
rts
Now, the problem is to identify which branch to select or to find a different solution.
The BCS
is not valid if the V2 subtraction clears the carry.
The BPL
in not valid if V1 is 'negative' (>$80).
It should be easy, but...
EDIT
I did not find in the aswers a real solution.
Let me try to follow the logic, firstly with the original values as in code.
SEC
V1
= $FFV2
=$85BCS
(to jump to label) nor BMI
since V2
is negative.With a different set, i.e. V1
=$1 and V2
=$0A I will have a result < 0, which is my goal to stop iterations.
Any suggestion?
Generally, a sequence like this (I've slightly amended the code in your question to make it more self contained)
V1 equ $91
V2 equ $90
lda #00
sta V2
lda #20
sta V1
Label:
sec
lda V2
sbc #2
sta V2
lda V1
sbc #10
sta V1
will work as expected. With the values used in the code, the carry will be cleared after the first subtraction and will be set again after the second. If it is not, then the most likely cause is a bug in your emulator. I have run this in an online 6502 emulation and the carry was set by the time it got to the final sta V1
. I also ran it in visual6502 and here is the trace output:
cycle ab db rw Fetch pc a x y s p
0 0000 a9 1 LDA # 0000 aa 00 00 fd nv‑BdIZc
0 0000 a9 1 LDA # 0000 aa 00 00 fd nv‑BdIZc
2 0002 85 1 STA zp 0002 00 00 00 fd nv‑BdIZc
4 0090 00 0 0004 00 00 00 fd nv‑BdIZc
5 0004 a9 1 LDA # 0004 00 00 00 fd nv‑BdIZc
7 0006 85 1 STA zp 0006 14 00 00 fd nv‑BdIzc
9 0091 14 0 0008 14 00 00 fd nv‑BdIzc
10 0008 38 1 SEC 0008 14 00 00 fd nv‑BdIzc
12 0009 a5 1 LDA zp 0009 14 00 00 fd nv‑BdIzC
15 000b e9 1 SBC # 000b 00 00 00 fd nv‑BdIZC
17 000d 85 1 STA zp 000d 00 00 00 fd nv‑BdIZC
19 0090 fe 0 000f fe 00 00 fd Nv‑BdIzc
20 000f a5 1 LDA zp 000f fe 00 00 fd Nv‑BdIzc
23 0011 e9 1 SBC # 0011 14 00 00 fd nv‑BdIzc
25 0013 85 1 STA zp 0013 14 00 00 fd nv‑BdIzc
27 0091 09 0 0015 09 00 00 fd nv‑BdIzC
As you can see at the end, the carry is set (denoted by a capital C).
There is another problem with your code, by the way. If you have 2000 (decimal), then to load it into two locations, you need to convert it to hex before you slice it into two bytes. If you load 0 into a zero page location and 20 decimal into its successor, you've actually loaded 20 * 256 = 5120. The hex for 2000 is $07d0
.
Following the latest edit to the question. Here is a simplified bit of code that subtracts $0a
from $90
with the carry clear.
clc
lda #$90
sbc #$0a
And here is the Visual 6502 trace
cycle ab db rw Fetch pc a x y s p
0 0000 18 1 CLC 0000 aa 00 00 fd nv‑BdIZc
0 0000 18 1 CLC 0000 aa 00 00 fd nv‑BdIZc
2 0001 a9 1 LDA # 0001 aa 00 00 fd nv‑BdIZc
4 0003 e9 1 SBC # 0003 90 00 00 fd Nv‑BdIzc
6 0005 ea 1 NOP 0005 90 00 00 fd Nv‑BdIzc
8 0006 ea 1 NOP 0006 85 00 00 fd Nv‑BdIzC
If your emulator leaves the carry unset in that situation, your emulator has a bug.