Table Registers

This page is a work in progress. It is incomplete, and may not be completely accurate or up to date. The wording or grammar is also in the process of being improved.

x86 has three main "table" registers: the Global Descriptor Table Register (GDTR), the Interrupt Descriptor Table Register (IDTR), and the Local Descriptor Table Register (LDTR). The Global Descriptor Table contains information about the various memory segments, the Interrupt Descriptor Table contains execution vectors for interrupts, and the Local Descriptor Table contains information about the currently executing task's segments. Despite their names, these registers do not contain the actual table's data, but only a pointer to the data in memory.

Global Descriptor Table

The Global Descriptor Table is a table detailing the memory segments of running threads. It is an array of the following 8 byte structure:

Interrupt Descriptor Table

In Protected and Long Mode, the Interrupt Descriptor Table details where the Interrupt Service Routines (ISR) are located. It is the counterpart to Real Mode's Interrupt Vector Table (IVT).

Due to the limitations of the Interrupt Vector Table, Intel created the Interrupt Descriptor Table. The big difference between the Interrupt Descriptor Table and the Interrupt Vector Table is the ability for privilege restrictions on code that calls an interrupt; This was previously not possible.

The LIDT instruction takes a pointer to a memory location containing the following data:

idtr:
  .limit: dw ?
  .base:  dd ?

These six bytes are what will be stored in the IDTR register. In this layout, idtr.limit is the byte count of the pointed to structure minus one. limit.base is the 32 bit linear address of the structure. A quirk of this design allows Interrupt Descriptor Tables containing more than 256 entries (8192 or 16384 bytes depending on mode) despite the fact that there are a maximum of 256 interrupts.

The layout of the referenced table depends on the current operating mode of the processor.

Protected Mode

In Protected Mode, the IDTR register references a table of eight byte entries of the following layout:

struct idt
  offsetLow:  resw 1
  selector:   resw 1
  zero:       resb 1
  flags:      resb 1
  offsetHigh: resw 1
endstruc

The fields of which are:

  • offsetLow (16 bits): The 16 least significant bits of the 32 bit linear offset of the vector. These will be combined with offsetHigh to form the address.
  • selector (16 bits): An index into either the Global Descriptor Table or the Local Descriptor Table.
  • zero (8 bits): A reserved byte. Must be set to zero.
  • flags (8 bits): A flag byte containing the following entries (from least significant to most significant bit):
    • type (bits 3 to 0): The type of gate this interrupt is. Valid values are:
      • 0b0101 (0x5): 32 bit task gate
      • 0b0110 (0x6): 16 bit interrupt gate
      • 0b0111 (0x7): 16 bit trap gate
      • 0b1110 (0xE): 32 bit interrupt gate
      • 0b1111 (0xF): 32 bit trap gate
    • s (bit 4): Storage segment. Clear for interrupt and trap gates, but set otherwise.
    • dpl (bits 6 and 5): Descriptor Privilege Level. The current task's processor ring must be equal to or less than this to call this interrupt.
    • p (bit 7): Present. Must be set for used (present) interrupts.
  • offsetHigh (16 bits): The 16 most significant bits of the 32 bit linear offset of the vector. These will be combined with offsetLow to form the address.

Long Mode

TODO

Interrupt Vector Table

TODO

Local Descriptor Table

TODO