Branching is kicking my rear end

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
halkun
Posts: 45
Joined: 26 Nov 2012

Branching is kicking my rear end

Post by halkun »

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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Branching is kicking my rear end

Post by BigEd »

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:

Code: Select all

loop:
lda $ea
cmp #1
beq loop
or, very similarly

Code: Select all

loop:
lda #1
cmp $ea
beq loop
which allows you to see how to go around the loop more quickly:

Code: Select all

lda #1
loop:
cmp $ea
beq loop
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.)
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Branching is kicking my rear end

Post by GARTHWILSON »

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:

Code: Select all

Loop:  LDA  $EA
       BNE  Loop     ; Drops through when you have a 0.
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.)
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?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Branching is kicking my rear end

Post by GARTHWILSON »

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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Branching is kicking my rear end

Post by BigEd »

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.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Branching is kicking my rear end

Post by GARTHWILSON »

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?
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: Branching is kicking my rear end

Post by White Flame »

halkun wrote:
Also, How would I effectively use BIT to do this?
BIT effectively performs an AND, to retain bits you're interested in, and ignore the rest via masking them off. It would be appropriate to use when checking for %xxxxxxx0 and %xxxxxxx1 (lda #1, bit $ea, bne/beq), but not specifically for %00000000 or %00000001 if 2-255 are also possible values.


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:
Maybe it could be code golfed down into 1, using bit shifting like

Code: Select all

 lda $ea
 lsr
 bne case2_255
 bcc case0
 bcs case1
but the way you word it, there is a stateful decision whether or not to perform the waiting for 0, based on a previous read.
kakemoms
Posts: 349
Joined: 02 Mar 2016

Re: Branching is kicking my rear end

Post by kakemoms »

For the 6502 (NMOS), the shortest possible loop to test bit0 in $ea would be:

Code: Select all

*=$e7
      LDA #0
      BEQ *0
Which would give you the code:

Code: Select all

$00e7   A9 00
$00e9   F0 FE
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).
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Branching is kicking my rear end

Post by Dr Jefyll »

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?? :P 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
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
kakemoms
Posts: 349
Joined: 02 Mar 2016

Re: Branching is kicking my rear end

Post by kakemoms »

Dr Jefyll wrote:
BTW, What the heck are you up to?? :P Will you share with us the background for this perplexing problem?

-- Jeff
If you are asking me.. eh.. it was just a crazy idea on how to make the loop faster. I have no idea what the original author is doing though. Probably some bit banging?

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.
Post Reply