The following figure 2, Figure 4 and Figure 5 are truncated from the Intel manual
The Global Descriptor table holds the segment descriptor in the Global Descriptor list, with each segment descriptor 8 bytes. In order to track the global descriptor list, there is a 48-bit register inside the processor called the Global Descriptor List Register (GDTR), GDTR is divided into two parts, 32-bit linear address and 16 boundary, and 32-bit linear base address part holds the global Descriptor list in memory of the starting linear addresses, The 16-bit boundary portion is the boundary (boundary) of the Global descriptor table whose value is equal to the size of the tables (total bytes)-1, since offset 0 starts. If the bounds value is 0, the size of the table is 1 bytes.
Because the GDT boundary is 16 bits, the table is 2 ^ 16 bytes, which is 65536 bytes (64KB), and because of a descriptor of 8 bytes, the table defines a maximum of 8,192 descriptors. After entering protected mode, the processor will immediately work in the new memory access mode, so GDT must be defined before entering protected mode, however, since real mode can only access 1MB of memory, the GDT is usually more defined in the memory range below 1MB, of course, allowing a different location after entering protected mode to redefine the GDT
Memory Segment Descriptor
Each descriptor occupies 8 bytes, the upper bit height is 32 bits in the image below, the lower 32 bits below
The segment descriptor specifies a 32-bit segment start address and a 20-bit segment boundary, in real mode, the segment address is not the physical address, and the physical address needs to be shifted to the left 4 bits. Unlike real mode, the segment address is 32 bits in 32-bit protected mode,If the paging feature is not turned on, the linear address is the physical address. The Subgrade address can be any address in the 0~4GB range, and the segment bounds are used to limit the extent of the segment, because the method of accessing the memory is offset by the subgrade address, so the offset is incremented from 0 for extended segments, such as code snippets and data segments, and the segment bounds determine the maximum value of the offset; For a down-extended segment, such as a stack segment, the segment bounds determine the minimum value of the offset.
The G-bit is the granularity bit, which is used to explain the meaning of the segment bounds, G = 0 o'clock, the segment bounds in bytes, the segment expands from 1 bytes to 1MB, because the segment bounds are 20 bits, and when G = 1 o'clock, the segment bounds are in 4KB bit units, so that the segment extends from 4KB to 4GB. The s bit is used to specify the type of descriptor, s = 0 o'clock, which means a system segment, S = 1 o'clock, which indicates a code snippet or data segment (stack also belongs to a special data segment) DPL represents the privileged level of the descriptor, the privilege levels are 0, 1, 2, 3, where 0 is the highest privilege level, and 3 is the least privileged, The code executed has 0 privilege levels (which can be seen as inherited from the processor), where the privilege level of the descriptor is used to specify the privilege level to which the segment must be accessed, and if the value here is 2, then only privileged 0, 1, and 2 programs can access the segment, and the processor blocks when privileged level 3 accesses it. P is the presence bit of a segment, the P-bit is used to indicate whether the segment corresponding to the descriptor exists, in general, the segment indicated by the descriptor is in memory. However, when the memory is tight, it is possible to just set up a descriptor, the corresponding memory space does not exist, at this time, the descriptor P-bit should be cleared 0, indicating that the segment does not exist. In addition, it is also in the case of memory tension, will be rarely used to swap out to the hard disk, make room for the memory of the program to use (currently executing), at this time, the same to the P-bit 0, when the turn it executes, then loaded into memory, and then the P position 1. The P-bit is checked by the processor, and whenever a segment in memory is accessed through a descriptor, if the P-bit is 0, the processor generates an interrupt, usually the interrupt handler is provided by the operating system, which is responsible for swapping the segment from the hard disk back into memory and P position 1, in a multiuser, multitasking system, This is a commonly used virtual memory scheduling strategy. The d/b bit is the default operand size or the default stack pointer size, which has different effects on different segments, and for code snippets, this bit is called the D-bit, which indicates the default offset address and operand size in the instruction, d = 0 is 16-bit, d = 1, indicates 32-bit . if d = 0, When the processor is executed in this segment, the 16-bit instruction pointer register IP will be used, and no 32-bit eip. is used for the stack segment, the bit is a B-bit for the use of an SP or ESP in an implicit stack operation, implicit stack instructions include push, Pop and call etc., if the bit is 0, the SP is used, the upper boundary bit of the stack segment 0xffff, is used ESP, the upperThe boundary is 0xFFFFFFFF. The L-bit is a 64-bit code bit that retains this bit to the 64-bit processor using a type of 4 bits, indicating the subtype of the descriptor, or category, for the data segment, X, E, W, a bit, X, C, R, and a bit for the code snippet     &NB sp; The above table, a bit is the access bit, each time the segment is accessed, the processor automatically places the location 1, the bit 0 is the software (operating system) responsible, by regularly monitoring the status of the bit, you can count the frequency of use of the segment. X is for execution, the e-bit indicates the extension direction, the W-bit indicates the writable, the C-bit indicates whether the segment is a privileged-level compliance, and C = 0 represents a code snippet that is not compliant, so that the code snippet can only be used by a privileged program, or by a gate call, and C = 1 means that the code Kewei from and entered. The code snippet can always be executed, but it cannot be written to prevent the program from being corrupted. Its R-bit is not used to limit the processor's readability, but rather to restrict the program, a typical example is to use the segment beyond the prefix CS: To access the memory in the code snippet. The AVL bit is a bit that the software can use, typically used by the operating system, and the processor does not use it.Segment Selection Sub
3~15 is the segment descriptor in the index of the descriptor, TI = 0 is the descriptor in the GDT, ti = 1 o'clock, descriptor in the LDT, RPL is the request privilege level, represents the current selection of the program's privileged level, it is the program requires access to this memory segment. Segment Descriptor Cache
As shown in the figure above, when running on a 32-bit processor, each segment register also includes an invisible part, called the descriptor cache, which holds the linear base address, segment bounds, and segment properties of the segment, and since it is not visible, the processor does not want us to access it. In fact, there is no way to access this invisible part, which is used internally by the processor. When the processor executes any instruction that changes the segment selector (such as pop, jmp, call, RET, etc.), the index number provided in the instruction (i.e. the index in the selection sub) is multiplied by 8 (a descriptor of 8 bytes) as the offset address, Add the linear base address provided in the GDTR to access the GDT, and if no problems are found (such as exceeding the bounds of the GDT), the found description is automatically Fugazai to the Invisible Descriptor cache section. The loaded sections include the linear base address of the segment, the segment bounds, and the access properties of the segment. Thereafter, whenever there is memory access, the descriptor in the GDT is no longer accessed, directly using the linear base address provided by the current segment register descriptor cache. Enter protected mode data read from 0x92 port, 2nd bit open A20, first bit = 1 reboot
In protected mode, do not allow the use of MOV instructions to change the contents of the segment register CS, such as: MOV cs, ax, attempts to do so will cause the processor to produce an invalid opcode of an abnormal interrupt.
Below is a section of the main guide area code, the experiment Environment book also said, my resources also have book resources download, there is said how to configure VirtualBox and Bochs, here say a configuration Bochs, book resources in the configuration Bochs
Disk&boot-to-ATA channel 0--and first HD/CD on channel 0--and Type of disk image This option is VPC, I use 2.6.2 to configure when the VPC fails to start, You have to choose Flat, 2.6.0 seems to choose VPC can
[Plain] View Plain copy print? mov ax, cs mov ss, ax         MOV SP, 0x7c00 ; calculate the logical segment address of the GDT location mov ax, [cs:gdt_base + 0x7c00] mov dx, [cs:gdt_base + 2 +0x7c00] mov bx, 0x10 div bx mov ds, ax ; Business segment Address mov bx, dx ; remainder is offset address ; Global Descriptor #0, The first item must be 0 mov dword [bx + 0x00], 0x00000000 mov dword [bx + 0x04], 0x00000000 ; Global Descriptor #1, Code snippet Descriptor ; Linear base Address: 0x00007c00, segment Bounds: 0x01ff, segment bounds are numerically equal to the length of the segment - 1, therefore the length of the segment is 0x200, , which is 512 bytes ; Granular bit byte (g = 0), belongs to memory segment (s = 1)        ; 32-bit segment (D/B = 1), in memory (P = 1) Privilege level bit 0 (dpl = 00) ; segment ; execute only (type = 1000) mov dword [bx + 0x08], 0x7c0001ff         MOV DWORD [BX + 0x0c], 0x00409800 ; Global Descriptor #2, Data segment Descriptor ; Linear Base Address: 0x000b8000, segment boundary: 0xffff ; granularity bit byte (g = 0), belongs to memory segment (S = 1) &nbSp; ; 32 bit segment (d/b = 1), in memory (p = 1) Privilege level bit 0 (dpl = 00) for ; segment ; readable writable, Extended Data segment (type = 0010) mov dword [bx + 0x10], 0x8000ffff mov dword [bx + 0x14], 0x0040920b ; Global Descriptor #3, Stack segment descriptor ; linear base address: 0x00000000, segment Bounds: 0x07a00 ; granularity bit byte (g = 0), belongs to segment of memory segment (S = 1) ; 32 bit (D/B  = 1), Privileged level bit 0 (dpl =) in memory (p = 1) ; segment 00) ; readable writable, down-scaled data segment, here is the stack segment ( type = 0110)         MOV DWORD [BX + 0x18], 0x00007a00 mov dword [bx + 0x1c], 0x00409600 ; Initialize Global descriptor Tabulation mov word [cs:gdt_size + 0x7c00], 31 ; Global Descriptor Descriptor Limit (total bytes - 1) lgdt [cs:gdt_size + 0x7c00] ; Load Global Descriptornbsp; ; Open a20 in al, 0x92 or al, 0x02 out 0x92, al cli ; Protection mode interrupt mechanism has not been established, off interrupt ; open protected Mode,  CR0 Register 0 position 1 mov eax, cr0 &nbSp or eax, 1 mov cr0, eax ; Enter protection mode, details see book p199 11.7 Empty pipelining serializers ; Note, Whatever you're using is a 16-bit transfer, . Or 32-bit far transfer ; because it is now in protected mode, The processor will treat the first parameter 0x0008 as a select sub ; logical segment address in real mode jmp dword 0x0008:_ProtectMode [ bits 32] _protectmode: ; Select the descriptors for sub-00000000000_10_000b, index 2 mov ax, 0x10 mov ds, ax mov byte [0x00], ' H ' mov byte [0x02], ' E ' mov byte [0x04], ' l ' mov byte [0x06 ], ' l ' mov byte [0x08], ' 0 ' mov byte [0x0a], ' ' mov byte [0x0c], ' O ' mov byte [0x0e], ' n ' mov byte [0x10], ' z ' mov byte [0x12], '. ' mov byte [0x14], '. ' mov byte [0x16], '. ' hlt ; the processor will not be woken up because of off interrupt, gdt_size dw 0 GDT_BASE    DD 0x7e00 times 510 - ($ - $$) db 0 dw 0xaa55