x86 GDT Descriptor layout

All timestamps are based on your local time of:

The lgdt instruction should be passed a 6-byte memory location. The first 16 bits form a word which is the size of the GDT table. Usually this is going to be a number that is 8*n - 1, where n=1,2,3,... The next 32 bits are the absolute linear address of the GDT table. These 6 bytes are loaded into the GDT register, and can then be overwritten if needed. The GDT table, however, must be in the specified memory location as long as it is needed.

Each entry in the GDT table is 8 bytes long. The first entry is the null descriptor, and is all 0's. The remaining entries have the following layout:

Bits 63-56: Bits 31-24 of the base address
Bit 55: Granularity bit (set means the limit gets multiplied by 4K)
Bit 54: 16/32-bit segment (0=16-bit, 1=32-bit)
Bit 53: Reserved, should be zero
Bit 52: Reserved for OS
Bits 51-48: Bits 19-16 of the segment limit
Bit 47: The segment is present in memory (used for virtual memory stuff)
Bits 46-45: Descriptor privilege level (0=highest, 3=lowest)
Bit 44: Descriptor bit (0=system descriptor, 1=code/data descriptor)
Bits 43-41: The descriptor type (see below for an enumeration of the types)
Bit 40: Accessed bit (again, for use with virtual memory)
Bits 39-16: Bits 23-0 of the base address
Bits 15-0: Bits 15-0 of the segment limit

The type of the segment is stored in bits 43-41, and has one of the following values:
Bit 43: executable (0=data segment, 1=code segment)
Bit 42: expansion direction (for data segments), conforming (for code segments)
Bit 41: read/write (for data segments: 0=RO, 1=RW) (for code segments: 0=Execute only, 1=Read/execute)

      ; stuff here
      lgdt [GDTR]
      ; more stuff here

GDTR:                                         ; GDT register data
      dw  GDT_End - GDT - 1                   ; 16-bit size limit of GDT
      dd  GDT                                 ; 32-bit linear address of GDT
      dd  0x00000000, 0x00000000              ; GDT[0]: null descriptor
      dd  0x0000FFFF, 0x00CF9C00              ; GDT[1]: code segment descriptor
      dd  0x0000FFFF, 0x00CF9200              ; GDT[2]: data segment descriptor

      ; yet more stuff here

When you use entries in the GDT, you have to load the segment register with the offset of the GDT entry from the start of the GDT table. (i.e. to use the code segment descriptor entry in the code above, you'd load the segment register with 0x8. To use the data segment, load the segment register with 0x10).

Since the GDT entries are all 8 bytes, this necessarily means that the lowest three bits of the segment register are zero. Not! Intel decided to use these three bits for something else: bit 2 indicates which table to use (0=GDT, 1=LDT). Bits 1-0 indicate the request privilege level.

Allowed expansions in comments/replies: [i]italic[/i], [u]underline[/u], [b]bold[/b], [code]code[/code], [sub]subscript[/sub], [sup]superscript[/sup], [url=http://some.url]linked text[/url]
Human verification: Sum of thirty-one and twelve =
(c) Kartikaya Gupta, 2004-2024. User comments owned by their respective posters. All rights reserved.
You are accessing this website via IPv4. Consider upgrading to IPv6!