6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 21, 2024 4:36 am

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Thu Feb 07, 2019 8:31 am 
Offline

Joined: Mon Nov 26, 2012 3:40 am
Posts: 42
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 8:59 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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:
loop:
lda $ea
cmp #1
beq loop

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

which allows you to see how to go around the loop more quickly:
Code:
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.)


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 9:22 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
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:
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 9:34 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 9:42 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 9:46 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
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:
        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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 07, 2019 9:23 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 674
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:
 ; 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:
 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.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 28, 2019 11:21 pm 
Offline

Joined: Wed Mar 02, 2016 12:00 pm
Posts: 343
For the 6502 (NMOS), the shortest possible loop to test bit0 in $ea would be:

Code:
*=$e7
      LDA #0
      BEQ *0


Which would give you the code:

Code:
$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).


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 01, 2019 1:09 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
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


Top
 Profile  
Reply with quote  
PostPosted: Sun Mar 03, 2019 7:22 pm 
Offline

Joined: Wed Mar 02, 2016 12:00 pm
Posts: 343
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: