Chapter 5: Interrupts

Often, events occur external to the central processing unit which require immediate action by the CPU. For example, suppose a device is receiving a string of 80 characters from the CPU, one at a time, at fixed intervals. There are two ways to handle such a situation:

  1. A program could be written which inputs the first character, stalls until the next character is ready (e.g., executes a timeout by incrementing a sufficiently large counter), then inputs the next character, and proceeds in this fashion until the entire 80 character string has been received.

    This method is referred to as programmed Input/Output.

  2. The device controller could interrupt the CPU when a character is ready to be input, forcing a branch from the executing program to a special interrupt service routine.

    The interrupt sequence may be illustrated as follows:

    Interrupt sequence: normal execution, interrupt service routine, execution continues

The 8080 contains a bit named INTE which may be set or reset by the instructions EI and DI described in Chapter 2. Whenever INTE is equal to 0, the entire interrupt handling system is disabled, and no interrupts will be accepted.

When the CPU recognizes an interrupt request from an external device, the following actions occur:

  1. The instruction currently being executed is completed.

  2. The interrupt enable bit, INTE, is reset = 0.

  3. The interrupting device supplies, via hardware, one instruction which the CPU executes. This instruction does not appear anywhere in memory, and the programmer has no control over it, since it is a function of the interrupting device’s controller design. The program counter is not incremented before this instruction.

The instruction supplied by the interrupting device is normally an RST instruction (see Chapter 2), since this is an efficient one byte call to one of 8 eight-byte subroutines located in the first 64 words of memory. For instance, the teletype may supply the instruction:

RST     0H

with each teletype input interrupt. Then the subroutine which processes data transmitted from the teletype to the CPU will be called into execution via an eight-byte instruction sequence at memory locations 0000H to 0007H.

A digital input device may supply the instruction:

RST     1H

Then the subroutine that processes the digital input signals will be called via a sequence of instructions occupying memory locations 0008H to 000FH.

Devices a and b supply RST 0H and RST 1H
Device x supplies RST 7H

Note that any of these 8-byte subroutines may in turn call longer subroutines to process the interrupt, if necessary.

Any device may supply an RST instruction (and indeed may supply any 8080 instruction).

The following is an example of an Interrupt sequence:

Interrupt from device 1 while executing at 3C0B

Device 1 signals an interrupt as the CPU is executing the instruction at 3C0B. This instruction is completed. The program counter remains set to 3C0C, and the instruction RST 0H supplied by device 1 is executed. Since this is a call to location zero, 3C0C is pushed onto the stack and program control is transferred to location 0000H. (This subroutine may perform jumps, calls, or any other operation.) When the RETURN is executed, address 3C0C is popped off the stack and replaces the contents of the program counter, causing execution to continue at the instruction following the point where the interrupt occurred.

Note

The original text says the return address is “pushed onto the stand”; this has been corrected to “stack”.

Writing Interrupt Subroutines

In general, any registers or condition bits changed by an interrupt subroutine must be restored before returning to the interrupted program, or errors will occur.

For example, suppose a program is interrupted just prior to the instruction:

JC      LOC

and the carry bit equals 1. If the interrupt subroutine happens to zero the carry bit just before returning to the interrupted program, the jump to LOC which should have occurred will not, causing the interrupted program to produce erroneous results.

Like any other subroutine then, any interrupt subroutine should save at least the condition bits and restore them before performing a RETURN operation. (The obvious and most convenient way to do this is to save the data in the stack, using PUSH and POP operations.)

Further, the interrupt enable system is automatically disabled whenever an interrupt is acknowledged. Except in special cases, therefore, an interrupt subroutine should include an EI instruction somewhere to permit detection and handling of future interrupts. Any time after an EI is executed, the interrupt subroutine may itself be interrupted. This process may continue to any level, but as long as all pertinent data are saved and restored, correct program execution will continue automatically.

A typical interrupt subroutine, then, could appear as follows:

Code    Operand     Comment
PUSH    PSW         ; Save condition bits and accumulator
EI                  ; Re-enable interrupts
  .                 ;
  .                 ; Perform necessary actions to service
  .                 ; the interrupt
  .
POP     PSW         ; Restore machine status
RET                 ; Return to interrupted program