Working With Bits
Change one bit without disturbing the rest. Meet ora, and and eor — set, clear and flip individual bits — the everyday way to throw a single switch in a byte.
Back in The Joypad in Your Hand you tested a single bit by masking it. Often you want to change one — set a flag, clear a flag, flip a flag — without touching the seven bits around it. Three instructions do exactly that, one bit at a time:
ora n— OR with A: set every bit that's 1 inn, leave the rest alone.and n— keep every bit that's 1 inn, clear the rest.eor n— Exclusive-OR: flip every bit that's 1 inn. (On the 6502, XOR is spelteor.)
A byte is often not one number but eight little switches — the controller you read in Unit 10 was exactly that, its buttons arriving bit by bit. These three instructions are how you throw one switch and leave the others where they were.
What you'll see by the end
A pink screen — colour $36. We started with $16 (red), ora'd in bit 5, and got $36. In bit terms it's "set one bit and leave the rest"; in colour terms, red lightened to pink. One switch thrown.
Setting a bit
; ============================================================================
; Meet the Machine (NES) - Unit 15: Working With Bits
;
; Change one bit without touching the other seven. ora sets, and clears, eor
; flips. Here we take red and set a single bit to turn it green.
; ============================================================================
.segment "HEADER"
.byte "NES", $1a
.byte 2
.byte 1
.byte $00, $00
.segment "CODE"
reset:
sei
cld
ldx #$40
stx $4017
ldx #$ff
txs
inx
stx $2000
stx $2001
stx $4010
warm1:
bit $2002
bpl warm1
warm2:
bit $2002
bpl warm2
; ----------------------------------------------------------- YOUR CODE START
lda #%00010110 ; $16 - red
ora #%00100000 ; SET bit 5, leave the rest alone
; -> %00110110 = $36 (a pink)
; ------------------------------------------------------------- YOUR CODE END
sta $00
bit $2002
lda #$3f
sta $2006
lda #$00
sta $2006
lda $00
sta $2007
forever:
jmp forever
nmi:
rti
irq:
rti
.segment "VECTORS"
.word nmi
.word reset
.word irq
.segment "CHARS"
.byte $00,$00,$00,$00,$00,$00,$00,$00
.byte $00,$00,$00,$00,$00,$00,$00,$00
.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
.byte $00,$00,$00,$00,$00,$00,$00,$00
.res 8192 - 32, $00
%00010110 is $16, red. ora #%00100000 sets bit 5 without disturbing the others, giving %00110110 = $36. The power of ora is that it's surgical: it only ever turns bits on, so whatever you already had survives. (On the NES palette, that higher bit is the "brightness" half of the colour code — which is why setting it lightened red toward pink.)
Assemble and run
ca65 bits.asm -o bits.o && ld65 -C nes.cfg bits.o -o bits.nes
Red, with one bit set, becomes pink.
Try this: clear a bit with and
Start from lda #%00111000 ($38) and and #%00110000. The and keeps only the bits that are 1 in the mask — so the bottom bits clear and you're left with %00110000 = $30 (white). and is the surgical off switch, the mirror of ora.
Try this: flip a bit with eor
Take any value and eor #%00100000. Bit 5 flips — on becomes off, off becomes on. Run it twice on the same value and you're back where you started: flipping twice undoes itself. (That reversibility is exactly why eor is the heart of some sprite-drawing tricks — a topic for later.)
If it doesn't work
ora/and/eorwon't assemble. They take an immediate mask:ora #%00100000. The#matters — without it you'd OR with the contents of an address, not the bits you wrote.- The colour didn't change as expected. Work the mask bit by bit against the starting value:
oraturns bits on,andkeeps the masked ones,eorflips. Sketch the eight bits if you have to. - The screen came out black. Some NES colour codes (the
$xD/$xE/$xFones) are black or blank — if your bit-twiddling lands on one, you'll see black. Pick bits that keep you on a visible colour.
What you've learnt
ora sets bits, and clears them, eor flips them — so you can change one bit of a byte and leave the other seven untouched.
What's next
A byte tops out at 255 — too small for a screen address, which runs to 65535. Next — Bigger Than a Byte — we hold a number in two bytes and add it by hand, and the carry flag from last unit turns out to be the bridge that makes it work.