Program-controlled I/O (polling) is the simplest way to talk to an I/O device. The processor sits in a tight loop reading the device’s STATUS register, waiting for it to indicate “ready,” then reads or writes the DATA register. The whole interaction is driven by the processor’s running program.

The structure of a polling loop:

WAIT:
    LoadByte R4, DEVICE_STATUS
    And      R4, R4, #READY_BIT   # mask the ready bit
    Branch_if_Zero R4, WAIT       # loop until ready
    LoadByte R5, DEVICE_DATA

Read status, check the ready flag, branch back to start if not ready. Once the flag is set, do the transfer.

Worked example: read a line from the keyboard

    Move R2, #LOC                ; R2 -> memory buffer
    Move R3, #CR                  ; Carriage Return ASCII

READ:
    LoadByte R4, KBD_STATUS
    And      R4, R4, #2           ; bit 1 (KIN)
    Branch_if_Zero R4, READ
    LoadByte R5, KBD_DATA         ; read clears KIN
    StoreByte R5, (R2)
    Add      R2, R2, #1

ECHO:
    LoadByte R4, DISP_STATUS
    And      R4, R4, #4           ; bit 2 (DOUT)
    Branch_if_Zero R4, ECHO
    StoreByte R5, DISP_DATA       ; write clears DOUT

    Branch_if_Equal R5, R3, EXIT  ; stop on CR
    Branch READ

EXIT:

The structure: poll keyboard → read character → poll display → echo character → check if it was Enter → repeat.

Pros

  • Simple. No interrupts, no special hardware, no asynchronous behavior to reason about.
  • Predictable timing. You know exactly when each byte gets read.
  • Easy to debug. Single thread of control.

Cons

  • Wastes CPU cycles. A keyboard might wait seconds between keypresses, but the processor spins flat-out checking the status. A 3 GHz CPU running a tight 4-instruction polling loop iterates about 750 million times per second, so per second of idle that’s hundreds of millions of useless iterations.
  • Can’t do other work. While polling, the processor isn’t running anything else.
  • Latency depends on the polling rate. If the loop is slow (the processor is doing other things between polls), characters can be missed when the device buffer fills up.

The waste is what motivates interrupts: let the device alert the processor when it’s ready, and the processor can do useful work in the meantime.

When polling is still right

Polling isn’t always wrong. It’s the right choice when:

  • The device transfers data continuously and at a high rate (e.g. reading from a fast disk into a tight loop, where interrupts would just add overhead).
  • The processor has nothing else to do.
  • The interrupt mechanism is unavailable or unreliable.
  • Latency must be minimal and deterministic (real-time systems sometimes prefer polling over interrupts for jitter reasons).

For most general-purpose computing, especially with slow human-input devices like keyboards and mice, interrupts win.