Quantcast
Channel: stardot.org.uk
Viewing all articles
Browse latest Browse all 2385

8-bit acorn software: other • Re: Unusual 6502 programming techniques

$
0
0
BIT is a very under-appreciated instruction!

It performs a logic AND between the accumulator and the contents of some address in memory (on the NMOS 6502 at least, it can only take a long or short address, not an immediate argument) but discards the result, only setting the Z flag as appropriate. But it also sets the N and V flags from bits 7 and 6 respectively of the contents of that address; meaning you can very quickly test the state of bit 7 or bit 6 of any memory location or input port. (The 74LS125 -- four independently-controllable tri-state buffers -- can be used to implement one-bit input ports.) If you precede the BIT instruiction with LDA #&20, you can even test three bits of a byte at once! (since Z=0 means bit 5 was set.)

There is no explicit SEV instruction, even although there is CLV and of course BVC and BVS; but if you need to use the (also under-appreciated) V flag to return an additional status bit (Acorn actually used this in a few rare system calls), you can set V=1 by performing a BIT on any memory address whose contents have bit 6 set, such as the first byte of an RTS or JMP instruction. And if you ever need to check for a non-zero high nybble, the first byte of a BEQ instruction is a convenient &F0 to BIT with.

The fact that none of the A, X or Y registers are changed also makes BIT useful for "masking-out" a two-byte or one-byte instruction. (Though it isn't the only instruction with this property; CMP / CPX / CPX could also be used.) Consider this code from a plotting routine, with multiple entry points depending whether we want to MOVE (PLOT 4), DRAW (PLOT 5) -- this being the thing we are expecting to do most often -- or PLOT using the mode already in the accumulator:

Code:

.move    LDA #&04    BNE send_KXY \ Always branches.draw    LDA #&05.send_KXY    PHA          \ Stash plot mode    LDA #&19     \ PLOT instruction    JSR oswrch    PLA          \ Retrieve plot mode    JSR oswrch.send_XY    \  send co-ordinates
Here the code at label move loads the accumulator with 4, then does a branch if not equal to 0 (which will always branch) to send_KXY. The code at draw loads the accumulator with 5, then falls through to send_KXY.

We can actually save a byte as follows:

Code:

.move    LDA #&04    EQUB &2C \ = opcode for BIT long.draw    LDA #&05.send_KXY    \  the rest unchanged
The first few bytes disassemble as

Code:

A9 04     LDA #&042C A9 05  BIT &05A948        PHA
The label move points to the first A9; which looks like LDA #&04 followed by BIT &05A9. The label draw points to the second A9, which looks like LDA #&05.

Note that the processor will perform a read on the address formed by the skipped instruction (here &05A9 which is in language workspace; probably the BASIC REPEAT stack), so watch out for instructions being turned into reads from hardware with sloppy address decoding.

Statistics: Posted by julie_m — Wed Aug 28, 2024 6:01 pm



Viewing all articles
Browse latest Browse all 2385

Trending Articles