Bitwise Operations and Masks: Byte Control Bit by Bit
A byte is eight independent switches living in one cell. How do you reach a single one of them without touching the rest? That is what bitwise operations are for: AND, OR and XOR are applied to a byte element by element, and the number paired with them is called a mask. Masks appear twice in the course: in the bus gates (BusAND/BusOR) and in the level 2.23 gamepad program.
Bitwise means element-wise
Ordinary addition links places together through carries. Bitwise operations do not: each pair of bits (byte, mask) is processed independently. In the i-th place of the result you get exactly what the operation's truth table yields for the i-th bits of the operands. That is why the bus versions of the gates in the course are simply eight ordinary gates side by side (in Verilog — a generate-for from level 4.37).
The tables are familiar: AND gives 1 only on two ones, OR — if there is at least one, XOR — when the bits differ. Not "numbers" but eight independent mini-computations.
A mask is a stencil for a byte
A mask is the second operand, chosen so that the needed places change and the rest do not. Four basic tricks for working with bit number k:
— Set (make 1): X OR (1 << k). The mask's ones "paint" ones over the byte.
— Clear (make 0): X AND NOT(1 << k) — a mask of all ones except position k. Remember 0xFE from the bus article? That is the mask "everything but the last bit".
— Toggle: X XOR (1 << k). XOR with a one always flips the bit.
— Test: X AND (1 << k). Non-zero result — the bit was 1; zero — it was 0.
The gamepad: reading buttons with masks
Level 2.23, "Gamepad", reads the buttons from port 254: the answer brings eight bits — one per button (1 — Up, 2 — Down, 4 — Left, 8 — Right). How do you find out whether "Left" is pressed? Apply the mask 4:
LDA 0 ; clear the accumulator
ADD 254 ; Acc = the button byte, e.g. 00000101 (Up + Left = 1 + 4 = 5)
AND 4 ; mask 00000100 — keep only the Left bit
JZ skip ; zero? button not pressed — jump
... ; we land here if Left is pressed
skip: HLT
Three lines — and the program "probes" one specific bit of an eight-bit byte. The same trick drives the snake on the Part 2 finale: polling buttons, checking directions, moving coordinates — all on AND masks and the flag jumps from the previous article.
Test yourself
Which operation sets bit 3 without touching the others?
OR with the mask 00001000: a one is "painted" into the right place, and OR does not change the remaining bits.
Why does AND 0xFF leave a byte unchanged while AND 0x00 wipes it?
AND with a one leaves the bit as-is; AND with a zero always gives 0. The mask 0xFF is all ones, 0x00 is all zeros.
What makes XOR useful for bit work?
It toggles: XOR with 1 flips the bit, XOR with 0 leaves it. Applying it twice restores everything.