Sunteți pe pagina 1din 7

More and more, efficient organizations are switching to Dell.

com hpc computing solutions to enhance their speed, efficiency, and ability to
tackle sophisticated high level analytics.

Interrupts and Exceptions

by Yariv Kaplan
Much of the functionality embedded inside a personal computer is implemented by hardware devices other than the processor. For
example, serial communication is handled by an Intel 8251A chip (or a 16550AF in newer computers), which is located on the
computer's motherboard (usually inside an ASIC) while the keyboard is controlled by a 8042A microprocessor.
Since each device operates at its own pace, a method is needed for synchronizing the operation of the processor with these devices.
One solution is for the processor to sit in a tight loop, asking each device about its current state (a method known as polling). When
data is available in one of the devices, the processor can then read and process the incoming bytes. While this method works, it has
many disadvantages. First, it is very wasteful in terms of processing power, since the processor is constantly busy reading the status
of the attached devices instead of executing some useful code. And second, when the rate of data transfer is extremely high, the
processor might lose data bytes arriving from the hardware devices.
So, a different approach was devised. Instead of polling hardware devices to wait for their response, each device is responsible for
notifying the processor about its current state. When a hardware device needs the processor's attention, it simply sends an electrical
signal (hardware interrupt) through a dedicated pin in the interrupt controller chip (located on the computer's motherboard).
The interrupt controller serves as an intermediate between the hardware devices and the processor. Its responsibility is to alert the
processor when one of the hardware devices needs its immediate attention. In this case, the processor stops its current activity and
jumps to execute a function (interrupt handler) which was previously associated with the calling device (or more accurately,
associated with the interrupt vector of the device).
While hardware interrupts have a significant importance, software interrupts also play a major role in the normal operation of the
PC. These interrupts are synchronous rather than asynchronous, since they are generated by the processor itself when it encounters
an INT instruction inside the code stream. Software interrupts are usually used by the operating system to publish its internal
functions, thereby allowing applications to take advantage of these services.
Exceptions belong to a special type of software interrupts. They are generated by the processor itself whenever some unexpected
critical event occurs. For instance, a page fault exception (interrupt 14) is triggered when the processor attempts to access a page,
which is marked as not-present. The exception handler can then reload the page from disk (virtual memory) and restart the
instruction which generated the exception.
Three types of exceptions can be generated by the processor: faults, traps and aborts. When a fault exception occurs, the CS and

(E)IP registers which are pushed on the stack, point to the address of the instruction, which generated the exception. This gives the
exception handler a chance to fix the condition which caused the exception to occur, before restarting the faulting instruction. Traps
are similar to interrupts in the sense that they make the processor push the address of the next instruction to the stack, while aborts
neglect to specify the location of the faulting instruction, since they are usually used to indicate severe errors (such as hardware
errors or illegal system tables) which are not recoverable.

Software Interrupts
If you've ever programmed for DOS, you probably know that the INT 21h interface has a salient importance in linking applications
with operating system services. For instance, calling an operating system function for opening a file, simply requires issuing an INT
21h interrupt with the correct parameters set in the processor registers.
The BIOS (Basic Input Output System) uses a similar software communication mechanism. The INT 10h, 13h and 16h are all
interfaces to internal BIOS functions, which control the screen, the disk controller and the keyboard. Instead of accessing hardware
devices directly, DOS uses the BIOS services to control the operation of the system. Modern operating systems such as Windows NT
drop their reliance upon the BIOS in favor of faster mechanisms (device drivers) for accessing the PC's hardware.
When the processor bumps into an INT instruction, it pushes the address of the next instruction (CS and IP registers) and the
contents of its flags register to the stack and then jumps to execute the interrupt handler. This ensures that when the handler code
ends, the processor returns automatically to the original code stream (the code which was executing before the interrupt occured).
Here are the precise steps taken by the processor when it encounters an INT instruction:
1. Push Flags, CS and IP to the stack (in this order).
2. Multiply interrupt number by 4 and use the resulting number as an offset into the interrupt table (located at the beginning of
the physical address space).
3. Get far address (CS and IP) of the interrupt handler from the table entry.
4. Disable interrupts (note that if you wish hardware interrupts to be serviced even when the processor executes inside an
interrupt handler, you must issue a STI instruction at the beginning of the handler code).
5. Jump to execute the handler.
6. When the handler code ends (an IRET instruction is executed), pop CS, IP and the flags from the stack so that control returns to
the currently active application.
Many applications (especially TSRs - Terminate and Stay Resident programs) hook software interrupts to supply additional services
on top of those offered by DOS and the BIOS. One good example is Netware 3.1, which hooks INT 21h in order to add support for
network file operations (such as reading a file located on a remote computer). Other pieces of code (mostly device drivers) hook
hardware interrupts to monitor various devices and ensure their proper operation.
To hook an interrupt, a program need only to replace a specific interrupt table entry with the address of its own interrupt handler.
Whenever this interrupt occurs, the handler is automatically invoked by the processor. A good programming practice is to place a call
to the previous handler inside the interrupt handling function. This ensures that all previously installed hooks will get a chance to
handle the incoming interrupt.

Note that when loading an application which uses software interrupts to call operating system services, there is no need to patch the
application code with the actual memory addresses of the OS services. Therefore, the operating system can freely relocate its
services in memory by simply updating the corresponding interrupt table entries with the new addresses.

Hardware Interrupts
Hardware interrupts are not very different in behavior. But still, when considering the path traveled by a hardware interrupt from the
instant it leaves the hardware device until it reaches the processor, you must take into account the actions taken by the interrupt
controller (or the 8259A if you prefer).
When the processor executes an INT instruction, it retrieves the interrupt code from the opcode itself. This code is later used by the
processor to index the IVT (interrupt vector table) and find the address of the interrupt handler. On the other hand, when a hardware
interrupt is detected, the interrupt controller sends the interrupt code to the processor via the data bus. When the code is finally
acquired by the processor (either from the INT opcode or from the interrupt controller) the steps taken are equivalent to those
discussed earlier.
Table 1 presents the interrupt vectors occupied by the interrupt controller chips under different operating systems:

Vectors occupied by the

master 8259A

Vectors occupied by
the slave 8259A


8h - Fh

70h - 77h

95 / 98

50h - 57h

58h - 5Fh


30h - 37h

38h - 3Fh

Table 1 - Interrupt vectors occupied by the 8259A chips

When executing in real-mode, the following exceptions are supported:
Exception Vector
by Zero
Debug /


Attempting to execute a DIV or an IDIV

instruction with a divisor which equals zero.

Used in conjunction with the debug registers

to indicate a breakpoint hit. The processor
also issues this interrupt after executing
every instruction when the TRAP flag is set.
The INT 3 instruction generates this
exception. Since the opcode of this


instruction is only one byte long, it is often

used by debuggers to set a breakpoint in
application code. The debugger needs only
to replace the first byte of the instruction
with the INT 3 opcode (11001100b) and wait
for the breakpoint exception to occur. After
the exception handler resumes execution
and before returning to the debugged
application, the debugger sets the INT 3
opcode to the previously overwritten byte
and issues an IRET (interrupt return)

When performing arithmetic instructions

with signed operands, the processor set the
OF flag to indicate an overflow. The INTO
instruction tests this flag and if it is set generates an exception.

The BOUND instruction is used to verify that

an array index does not exceed a certain
limit. If the limit is exceeded, an exception
is generated.

Occurs when the processor executes one of

the reserved opcodes or uses the LOCK
prefix improperly. Can also indicate an
invalid operand following an opcode.

Attempting to execute a floating-point

instruction when there is no coprocessor
installed. The EM bit of the CR0 register can
be cleared to disable this exception.


An interrupt occurs which has no

corresponding entry in the IVT or a second
exception is generated while the processor
is executing a previously activated exception








Stack operation exceeds offset FFFFh or a

selector pointing to a non-present segment
is loaded into SS.
Word memory access at offset FFFFh or an

FloatingPoint Error



attempt to execute past the end of the code

An error with the numeric coprocessor
(Divide-by-Zero, Underflow, Overflow...).

Table 2 - Real-Mode exceptions

Other exceptions exist only in Virtual 8086 Mode:

Exception Vector


Task State


Indicates that one of the checks made

during a task switch failed.



Loading one of the segment registers with a

selector to a segment marked as notpresent.

Page Fault


Accessing a supervisor page from user

privileged code or attempting to access a
page which is marked as not-present.



Memory access to an unaligned memory

location (can only occur while executing ring
3 code).

Table 3 - Virtual-Mode exceptions

Handling interrupts in protected-mode requires setting up a table in memory known as the IDT (Interrupt Descriptor Table). The IDT
is somewhat different from the interrupt vector table that exists in real-mode. Instead of being "stuck" at physical address 0, the
protected-mode IDT can float around in the linear address space with absolute freedom (although it is possible to change the address
of the IVT while in real-mode, it is incompatible with the implementation of the 8086 processor). The linear address of the IDT is
determined by a value set into the IDTR register using the LIDT instruction. Each entry in the IDT is 8 bytes long (as opposed to the 4
bytes entries of the IVT) and can contain one of three gate descriptors:
A task gate - Causes a task switch to occur.
An interrupt gate - Control is transferred to the interrupt handler with interrupts disabled.
A trap gate - Control is transferred to the interrupt handler (the interrupt flag remains unchanged).
The following figure presents the internal structure of a trap gate entry:

Figure 1 - Structure of a trap gate entry

Trap and interrupt gates have much in common since they are both used for control transfers between different privilege levels. The
selector and offset fields specified in these gate descriptors are used to locate and execute the interrupt handler code. A control
transfer is only permitted to a code residing in the same or a higher privilege level but never to a lower privileged one.

Software Interrupts
Software interrupts are still widely used by protected-mode operating systems in order to publish their internal services to the
external world. However, most of these interfaces are now wrapped by functions and cannot be accessed directly (although it's
possible, it's not recommended). For instance, Windows NT uses the undocumented interrupt 2Eh to allow control transfers between
its user mode and kernel mode components. Whenever a non-privileged Windows application issues a call to an API function, the
system routes the call until it reaches an INT 2Eh instruction. The IDT gate corresponding to this interrupt points to a handler inside
ntoskrnl, which performs the required privileged operations on behalf of the application. Windows 95 and 98 use a similar technique
to hop between user and kernel mode, but rely upon INT 30h instead of using INT 2Eh.

Hardware Interrupts
Hardware interrupts in protected-mode behave in the same manner as described in the real-mode section. The only major difference
is that when executing in protected-mode, the processor consults its IDT rather than searching the real-mode IVT for the address of
the interrupt handler.

Most of the information which was presented in the previous sections, applies to protected-mode as well. However, exception 13
(General Protection Fault) has a wider meaning in protected-mode and can indicate additional conditions than those defined for realmode.
That's it. More information about the implementation of interrupts and exceptions in protected-mode can be obtained from the

"Pentium Processor User's Manual" available from Intel.

Copyright 1997-2010 Yariv Kaplan