Show understanding of how bit manipulation can be used to monitor/control a device

4.3 Bit Manipulation

Learning objective

Show understanding of how bit manipulation can be used to monitor and control a device, and be able to implement the techniques in both a high‑level language (C/Python) and the Cambridge assembly language (9618).

Recall – binary, hexadecimal and two’s‑complement

  • Binary base‑2 uses bits 0–1. Each position represents a power of 2 (2⁰, 2¹, …).
  • Hexadecimal base‑16 groups four bits: 0x0–0xF (0000–1111₂).
  • Two’s‑complement represents signed numbers: invert all bits and add 1 to obtain the negative.
  • Example: 0b1111 0110 = 0xF6 = –10 in two’s‑complement (8‑bit).

Why manipulate bits?

  • One byte (8 bits) can represent 256 different states – perfect for compact I/O registers.
  • Each bit can act as an independent flag (sensor, LED, error, etc.).
  • Reading or changing a single flag does not disturb the other flags.
  • Bit‑wise operations are extremely fast and use minimal memory – essential in embedded systems.

Bit‑wise operators (C / Python style)

OperatorNameEffect
&ANDResult bit = 1 only if both operands are 1.
|ORResult bit = 1 if either operand is 1.
^XORResult bit = 1 if the operands differ.
~NOTFlips every bit (two’s‑complement representation).
<<Logical left shiftMoves bits left, inserting 0s on the right; MSB is discarded (or placed in the carry flag).
>>Logical right shiftMoves bits right, inserting 0s on the left; LSB is discarded (or placed in the carry flag).
arith >>Arithmetic right shiftPreserves the sign bit when shifting a signed value.
rol / rorRotate left / rightCyclic shift – bits that fall off one end re‑appear on the opposite end; no loss of information.

Shift operations – detailed examples

  • Logical left shiftval << 1 multiplies an unsigned value by 2. The original MSB is lost; the processor may set the carry flag (C) to the discarded bit.
  • Logical right shiftval >> 1 divides an unsigned value by 2, inserting 0 at the MSB.
  • Arithmetic right shiftval >> 1 on a signed two’s‑complement value copies the sign bit into the new MSB, preserving the sign.
  • Rotate leftrol val moves every bit left; the original MSB becomes the new LSB.
  • Rotate rightror val moves every bit right; the original LSB becomes the new MSB.

Representing a device register

Assume an 8‑bit I/O register PORTA located at address $20. A typical mapping is shown below.

Bit 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
|   |   |   |   |LED1|LED0|SW1|SW0|
+---+---+---+---+---+---+---+---+
  • Bits 0‑1 : Switch inputs (read‑only)
  • Bits 2‑3 : LED outputs (write‑only)
  • Bits 4‑7 : Reserved – must be preserved when writing.

Register‑transfer notation (RTN) for the register

SymbolMeaning
PORTAI/O register (8‑bit)
ACCAccumulator (working register)
MAR←PCMemory address register receives program counter
PC←PC+1Program counter increments
ACC←PORTARead register into accumulator
PORTA←ACCWrite accumulator back to register

Creating bit masks

A mask isolates or modifies particular bits. The mask for a single bit at position n is 1 << n. Masks can also cover a field of several bits.

NameBit(s)Mask (binary)Mask (hex)
LED020b000001000x04
LED130b000010000x08
SW000b000000010x01
SW110b000000100x02
MODE (bits 4‑6)4‑60b011100000x70

Setting a multi‑bit field

// Set MODE bits (bits 4‑6) to value 5 (binary 101)
uint8_t mode = 5;                     // 0b101
PORTA = (PORTA & ~0x70) | (mode << 4);
//          ^ clear field   ^ insert new value

Reading a flag (test)

// Test whether Switch 1 (SW1) is HIGH
if (PORTA & 0x02) {        // 0x02 = 1 << 1
    // switch is high
}

Setting, clearing and toggling a flag

Test‑and‑set (handshaking) pattern

// C style
if (STATUS_REG & 0x80) {          // bit 7 = over‑temperature?
    CONTROL_REG |= 0x01;         // start cooling fan (bit 0)
}

Assembly (Cambridge 9618 syntax) – immediate & direct addressing

    ;--- test bit 7 of STATUS_REG (direct address $30) -----------------
    LDA   $30          ; ACC ← STATUS_REG
    AND   #$80         ; test over‑temperature flag
    BEQ   noAlarm      ; branch if flag = 0

    ;--- set fan‑ON bit (bit 0 of CONTROL_REG at $31) ---------------
    LDA   $31          ; ACC ← CONTROL_REG
    ORA   #$01         ; set bit 0
    STA   $31          ; write back
noAlarm:

Monitoring & controlling devices – three worked examples

1. LED & switch panel (single‑bit flags)

while (1) {
    uint8_t sw = PORTA & 0x03;          // read SW0‑SW1
    PORTA = (PORTA & ~0x0C) | (sw << 2); // mirror switches onto LEDs
}

2. Temperature‑sensor status register (single‑bit alarm)

// Bits in SENSOR_STATUS (address $40)
// 7 – Over‑temperature alarm
// 6 – Sensor fault
// 5‑0 – Reserved

if (SENSOR_STATUS & 0x80) {          // alarm?
    CONTROL_REG |= 0x02;            // fan ON (bit 1)
} else {
    CONTROL_REG &= ~0x02;           // fan OFF
}

3. Multi‑status byte – extracting a 4‑bit error code

uint8_t raw = DEV_STATUS;          // read once (address $50)

uint8_t errorCode = (raw & 0xF0) >> 4;   // bits 7‑4
bool dataReady   = (raw & 0x08) != 0;    // bit 3
bool overflow    = (raw & 0x04) != 0;    // bit 2

Detecting overflow after a left shift – using the carry flag

In many 8‑bit processors the bit shifted out of the MSB is placed in the carry flag (C). The flag can be examined to decide whether an overflow occurred.

    LDA   $20          ; ACC ← PORTA (example value 0x90)
    ASL              ; arithmetic shift left – same as logical left for unsigned
    BCC   noOverflow   ; branch if Carry = 0 (no overflow)
    ; overflow handling code here
noOverflow:
    STA   $20          ; store shifted result

Assembly‑level illustration (Cambridge syntax) with RTN

;--- set LED0 (bit 2) ---------------------------------------------
    LDA   $20          ; ACC ← PORTA          (ACC←PORTA)
    ORA   #$04         ; ACC ← ACC OR 0x04   (ACC←ACC|mask)
    STA   $20          ; PORTA ← ACC          (PORTA←ACC)

;--- clear LED0 -----------------------------------------------
    LDA   $20
    AND   #$FB         ; mask = ~0x04
    STA   $20

;--- toggle LED1 -----------------------------------------------
    LDA   $20
    EOR   #$08         ; XOR with mask
    STA   $20

;--- test‑and‑set example (over‑temperature → fan) ---------------
    LDA   $30          ; ACC ← STATUS_REG
    AND   #$80
    BEQ   noAlarm
    LDA   $31          ; ACC ← CONTROL_REG
    ORA   #$01
    STA   $31
noAlarm:

Assessment Objective (AO) mapping

  • AO1 – Knowledge and understanding
    • Recall of binary, hexadecimal and two’s‑complement representations.
    • Definition of each bit‑wise operator and shift/rotate operation.
    • Explanation of why bits are used for I/O registers.
  • AO2 – Application of knowledge
    • Creating single‑ and multi‑bit masks with 1 << n.
    • Using &, |, ^, ~ to test, set, clear and toggle flags.
    • Extracting fields from a status byte (mask + shift).
    • Writing equivalent assembly instructions (direct & immediate addressing).
  • AO3 – Analysis and evaluation
    • Choosing the correct shift type (logical vs arithmetic) for signed data.
    • Evaluating the effect of a write on reserved bits and preserving them.
    • Detecting overflow via the carry flag and deciding on error handling.
    • Designing a test‑and‑set handshaking routine for reliable device control.

Summary checklist (what you must be able to do)

  1. Identify the bit‑to‑signal mapping for a given device register and document it using a byte diagram.
  2. Form masks:
    • Single‑bit: 1 << n (e.g., 0x04 for bit 2).
    • Multi‑bit field: ((1 << width)‑1) << lowPos (e.g., 0x70 for bits 4‑6).
  3. Use & to test, | to set, &~ to clear, and ^ to toggle individual or grouped bits.
  4. Combine masks with logical operators (&&, ||) to make multi‑condition decisions.
  5. Apply shift operations correctly:
    • Logical left/right for unsigned data.
    • Arithmetic right for signed two’s‑complement values.
    • Rotate when no bit loss is desired.
  6. Detect overflow or under‑flow by checking the processor’s carry flag after a shift.
  7. Translate every C‑style manipulation into Cambridge assembly, using:
    • Immediate addressing (#mask) for constants.
    • Direct addressing ($addr) for registers.
    • Register‑transfer notation to show the data flow.
  8. Preserve reserved or unused bits by masking them out before writing back to a register.
  9. Explain how the above techniques satisfy AO1‑AO3 in exam answers.
Suggested diagram: a byte diagram labelled LED0, LED1, SW0, SW1 with arrows indicating “read” (from switches) and “write” (to LEDs) operations.

Create an account or Login to take a Quiz

76 views
0 improvement suggestions

Log in to suggest improvements to this note.