I want to test if a value located at $EA is 0 or 1. if it's a 1, I want to repeat the test until it turns into a 0. I know I can use AND or BIT but my branching skills are weak. How do I test this?
Loop:
lda $#01
and $EA
BPL loop
something like that?
Also, How would I effectively use BIT to do this?
Branching is kicking my rear end
Re: Branching is kicking my rear end
There must be very many ways of doing this! It boils down to
- an instruction which sets a flag
- a branch which tests the flag
Probably simplest, conceptually, is to compare against the value you care about:
or, very similarly
which allows you to see how to go around the loop more quickly:
Instead of comparing, you could subtract, or and, or bit. Compare and subtract are very similar, as are and and bit. In the case of both compare and bit, the computation is performed but the accumulator is unchanged.
(The trouble with BPL is that you're testing the difference between a positive and a negative result, but the operation you've used can only return a positive result, zero being a positive value.)
- an instruction which sets a flag
- a branch which tests the flag
Probably simplest, conceptually, is to compare against the value you care about:
Code: Select all
loop:
lda $ea
cmp #1
beq loop
Code: Select all
loop:
lda #1
cmp $ea
beq loop
Code: Select all
lda #1
loop:
cmp $ea
beq loop
(The trouble with BPL is that you're testing the difference between a positive and a negative result, but the operation you've used can only return a positive result, zero being a positive value.)
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Branching is kicking my rear end
If there's no possibility of it being anything but 0 or 1, or if the only thing of interest is whether it's a 0 or not, just branch on the Z flag that's automatically set or cleared when you load the accumulator:
Is the variable at address $00EA (which really should have a name that's meaningful to humans, rather than just an address) going to be affected by an interrupt? If not, how will it ever change while you're running this loop? Is it I/O? (I doubt you're doing preemptive multitasking.)
Code: Select all
Loop: LDA $EA
BNE Loop ; Drops through when you have a 0.http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Branching is kicking my rear end
Actually, if you have a Rockwell or WDC 65c02 and you only need to test one bit (bit 0 in this case), you can do the whole loop with a single 3-byte instruction, BBS (Branch on Bit Set), specifically BBS0. If bit 0 of the contents of the given address is a 1, you'll branch back to where you specify, which in this case is back to the same instruction! The one instruction reads the ZP address specified, tests the bit specified, and branches on the condition specified, the distance specified, in the direction specified.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Branching is kicking my rear end
Ah, yes, of course, checking for zero is even easier!
It's a good lesson too: do we really need to be testing the full byte value, or just one specific bit, and what assumptions can we make? That's not all spelled out in the original post, and normally won't be all spelled out, but it can affect the solution. A fully defensive solution would check for invalid values and do something appropriate. Normally you'd see the opposite: an efficient solution which makes as many assumptions as are justified.
It's a good lesson too: do we really need to be testing the full byte value, or just one specific bit, and what assumptions can we make? That's not all spelled out in the original post, and normally won't be all spelled out, but it can affect the solution. A fully defensive solution would check for invalid values and do something appropriate. Normally you'd see the opposite: an efficient solution which makes as many assumptions as are justified.
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Branching is kicking my rear end
In situations where the number in a processor register could be anything but you specifically want to test for a 1 or an $FF, another trick to save a byte is to use DEA (or DEC A, decrement accumulator, available on the CMOS 6502, ie, 65c02) or DEX or DEY to turn a 1 into a 0, or INA (again 65c02) or INX or INY to turn an $FF into a 0, then branch on the Z flag. DEA, DEX, DEY, INA, INX, and INY each take one byte, whereas CMP#, CPX#, and CPY# take two. (Timing is the same though.) The usage assumes it's ok to alter the register contents. If you want to test for a series, you can do something like:
Code: Select all
DEA ; If the number in A was a 1,
BEQ routine1 ; branch to this routine.
DEA ; If it was a 2,
BEQ routine2 ; branch to this one.
DEA ; If it was a 3,
BEQ routine3 ; branch to this one.
<continue> ; Otherwise, run this default.http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
-
White Flame
- Posts: 704
- Joined: 24 Jul 2012
Re: Branching is kicking my rear end
halkun wrote:
Also, How would I effectively use BIT to do this?
From reading your original post, what you describe is basically a state machine, so I can't help but see it as 2 different comparisons:
Code: Select all
; First part, check if it's 1
ldx $ea ; using .X for byte-brevity of dex, vs .A and cmp
dex
bne skip
; Second part, conditionally wait until it's zero
loop:
ldx $ea
bne loop
skip:Code: Select all
lda $ea
lsr
bne case2_255
bcc case0
bcs case1Re: Branching is kicking my rear end
For the 6502 (NMOS), the shortest possible loop to test bit0 in $ea would be:
Which would give you the code:
If ONLY bit0 of $ea changes from 0 to 1, the routine continues as $ea memory content is changed into $ff. It does take a few cycles to get through the undefined opcode $ff though, so maybe not the fastest positive. This would not work on a WDC65C02 as the $ff is a branch instruction (but that solution was described above).
Code: Select all
*=$e7
LDA #0
BEQ *0
Code: Select all
$00e7 A9 00
$00e9 F0 FE
Re: Branching is kicking my rear end
Can I ask, is it crucially important that it be bit 0 which controls the stop/go? Presently, things are arranged so location $EA contains the operand $FE or $FF, and (somehow) you're causing bit 0 of that operand to vary.
If it were acceptable for bit 5 to control the stop/go then you could arrange things so $EA contained either the opcode $DO or the opcode $FO -- IOW, it would vary between BNE and BEQ. (The operand $FE could remain unchanged.) This would almost instantly control whether the program stalls in a loop or advances.
BTW, What the heck are you up to??
Will you share with us the background for this perplexing problem?
( Back in the 20th century I faced a perhaps similar challenge. Upgrading the floppy-disk interface for a Z80-based SBC from 5" to 3.5" floppies meant the data rate had doubled... and also doubled was the speed at which the Data-Ready pin on the Floppy Controller Chip needed to be sampled. The most easily implemented solution turned out to be pretty wonky. )
-- Jeff
If it were acceptable for bit 5 to control the stop/go then you could arrange things so $EA contained either the opcode $DO or the opcode $FO -- IOW, it would vary between BNE and BEQ. (The operand $FE could remain unchanged.) This would almost instantly control whether the program stalls in a loop or advances.
BTW, What the heck are you up to??
( Back in the 20th century I faced a perhaps similar challenge. Upgrading the floppy-disk interface for a Z80-based SBC from 5" to 3.5" floppies meant the data rate had doubled... and also doubled was the speed at which the Data-Ready pin on the Floppy Controller Chip needed to be sampled. The most easily implemented solution turned out to be pretty wonky. )
-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
Re: Branching is kicking my rear end
Dr Jefyll wrote:
BTW, What the heck are you up to??
Will you share with us the background for this perplexing problem?
-- Jeff
-- Jeff
Anyway..I think your idea is better. It makes the a BEQ into a BNE (or vice versa), so works on all versions of the 6502.