Unlike base, limit or offset, the attribute bits have no inherent bit numbers outside their use in the descriptor. You can say that bit 0 of the base is in bit 16 of the descriptor; But there is no real basis for saying something like "bit ? of the attributes is in bit 40 of the descriptor.

Despite that, I have found it very useful to invent a bit numbering for the attributes:

Bits 8 to 15 of the attributes are in descriptor bits 40 to 47

Bits 0 to 7 of the attributes of a gate are in descriptor bits 32 to 39

Bits 4 to 7 of the attributes of a nongate are in descriptor bits 52 to 55

Bits 0 to 3 of the attributes of a nongate don't exist (a nongate descriptor has room for only 12 attribute bits and I chose to number them 4 through 15)

Descriptor byte

6

5

4

Descriptor bits

55..52

51..48

47..........40

39..........32

Gate Attribute bits

15..........................0

nonGate Attribute bits

7....4

15..........8

This numbering gives me a consistent way to pass all the attributes together as a 16-bit value to any subroutine or macro that builds descriptors. It also gives me a consistent way to define symbolic constants for attribute values that can be combined in source code without regard to which bytes of the descriptor the bits end up in.

Bits marked "Z", "?", or "Avail" in the above table have no documented meanings. The descriptor will work correctly if all these bits are set to zero. The descriptor MAY work correctly if some of them are not zero. The documentation I have seen seems to indicate that those marked "Z" must be zero. Often this means Intel plans to assign a meaning to them later or has already assigned a meaning not covered by the documentation I read. The ones marked "Avail" are explicitly documented as being ignored by the CPU, so the programmer can use them for some other purpose. The ones marked "?" aren't mentioned one way or the other.

Attribute bit 15, "Present" must be set for a descritor to be used. Otherwise a fault will result. Clearing it is useful when implementing segment based virtual memory.

Attribute bit 11 in a gate or a TSS, "32bit" is set to indicate the 32 bit version. In an interrupt or trap gate IDT this bit decides whether the eip,cs,flags pushed on the stack are 16 bit or 32 bits each.

Attribute bits 0 to 4 in a call gate are the parameter count.

Attribute bit 7 in a nongate, "gran" controls the granularity of the limit field.
When this bit is clear the limit is equal to the value in the limit field. When
this bit is set:
limit = ( limit_field SHL 12 ) + 0xFFF

Attribute bit 9 in a TSS, "B" is set to indicate that the TSS is busy.

Attribute bit 6 in a code or data segment, "big" indicates the default size. In CS it controls the default for operand size and address size. In SS it controls the choice of sp vs. esp for push, pop (etc.). In DS, ES, FS, GS it has no effect.

Attribute bit 10 in a code segment, "C" is set for "conforming" code segments. See Intel documentation. If you don't understand this feature, don't set this bit.

Attribute bit 10 in a data segment, "E" is set for "expand down" data segments. See Intel documentation. If you don't understand this feature, don't set this bit.

Attribute bit 9 in a code segment, "R" is set to make a segment you can execute or read. It is cleared for execute-only. A code segment never permits write.

Attribute bit 9 in a data segment, "W" is set to make a segment you can read or write. It is cleared for read-only. A data segment never permits execute.

Attribute bit 8 in a code or data segment, "Acc" is set by the CPU to indicate that the segment has been accessed. If you do not want the CPU to do that extra write on the first access, you can preset the bit yourself.

This file defines constants and macros to help you create GDT, LDT and IDT descriptors. By using these constants and macros, you can make your source code more readable and maintainable than with the usual methods of creating descriptors.

The CPU does not use the first 8 bytes of the GDT. I always use those bytes to hold the psuedo-descriptor required by the LGDT instruction. That means that the address of the psuedo-descriptor is the same as the address of the GDT itself.

My start_gdt macro creates the psuedo-descriptor in the first 8 bytes of the GDT.

The psuedo descriptor consists of a word giving the limit (length in bytes minus one) of the GDT, followed by a dword giving the GDT's linear address. (The fourth word is not used).