中国优秀设计网站有哪些,直接用apk 做登陆网站,域名在线解析,8x8x8x新的网址入口继续深入探讨Windows系统中的GDT和LDT结构#xff0c;并解释段、选择子与对象、句柄的关系#xff0c;以及核心对象的概念。
GDT和LDT描述符的具体结构#xff08;复习并补充#xff09;
在x86架构中#xff0c;描述符#xff08;Descriptor#xff09;是一个8字节…继续深入探讨Windows系统中的GDT和LDT结构并解释段、选择子与对象、句柄的关系以及核心对象的概念。GDT和LDT描述符的具体结构复习并补充在x86架构中描述符Descriptor是一个8字节64位的数据结构用于定义内存段代码段、数据段、系统段等的属性。GDT和LDT中的描述符结构相同但用途不同。描述符的详细结构以代码/数据段为例一个描述符由以下字段组成段基址Base Address32位指定段在4GB线性地址空间中的起始地址。段限长Segment Limit20位指定段的大小。实际限长取决于粒度位G。粒度位Granularity, G如果G0则段限长以字节为单位最大1MB如果G1则段限长以4KB为单位最大4GB。默认操作数大小位Default operation size, D/B对于代码段D1表示32位代码段D0表示16位代码段。对于数据段B1表示32位数据段B0表示16位数据段。类型Type4位用于指定描述符的类型代码段、数据段、系统段等。描述符特权级Descriptor Privilege Level, DPL2位指定描述符所代表段的特权级0-3。段存在位Segment Present, P1位指示段是否存在于内存中。系统标志System, S1位S1表示代码段或数据段S0表示系统段如LDT、TSS等。描述符在内存中的布局从低地址到高地址字节0-1段限长的低16位。字节2-4段基址的低24位字节2、3、4分别对应基址的0-7、8-15、16-23位。字节5访问权限包括P、DPL、S、Type。字节6包含限长的高4位位16-19和标志G、D/B、保留位。字节7段基址的高8位位24-31。系统段描述符如LDT、TSS系统段描述符与代码/数据段描述符类似但类型字段Type的含义不同。例如LDT描述符的类型为0010十进制2TSS描述符的类型为1001十进制9非忙或1011十进制11忙。三个进程的GDT和LDT结构示例假设我们有三个进程进程A、进程B和系统进程内核。每个进程都有自己的LDT而GDT是全局的包含所有进程的LDT描述符和TSS描述符以及内核的段描述符。GDT结构简化假设每个进程有一个LDT和一个TSS假设GDT的条目如下每个条目8字节索引 选择子假设RPL0 描述符类型 用途0 0x0000 空描述符 必须为01 0x0008 内核代码段 内核代码DPL02 0x0010 内核数据段 内核数据DPL03 0x0018 用户代码段共享 用户代码模板DPL34 0x0020 用户数据段共享 用户数据模板DPL35 0x0028 LDT描述符进程A 指向进程A的LDT6 0x0030 TSS描述符进程A 指向进程A的TSS7 0x0038 LDT描述符进程B 指向进程B的LDT8 0x0040 TSS描述符进程B 指向进程B的TSS9 0x0048 LDT描述符系统进程 指向系统进程的LDT可选10 0x0050 TSS描述符系统进程 指向系统进程的TSS注意选择子由索引乘以8得到因为每个描述符8字节加上RPL最低2位。例如索引1的选择子为0x0008二进制0000 0000 0000 1000TI0查GDTRPL0。进程A的LDT结构进程A的LDT可能包含多个段描述符例如索引 选择子TI1RPL3 描述符类型 用途0 0x0007 代码段 进程A的代码段基址0x00400000限长0x3FFFFDPL31 0x000F 数据段 进程A的数据段基址0x00800000限长0x7FFFFDPL32 0x0017 堆栈段 进程A的堆栈段基址0x00C00000限长0x1FFFFDPL3注意当选择子TI1时表示查LDT。进程A的LDT选择子为0x0028GDT索引5TI0RPL0。当进程A运行时LDTR寄存器被加载为0x0028即指向GDT中进程A的LDT描述符。然后在进程A中访问代码段时可能使用选择子0x0007即LDT索引0TI1RPL3。进程B的LDT结构类似地进程B的LDT索引 选择子TI1RPL3 描述符类型 用途0 0x0007 代码段 进程B的代码段基址0x20000000限长0x5FFFFDPL31 0x000F 数据段 进程B的数据段基址0x30000000限长0x9FFFFDPL32 0x0017 堆栈段 进程B的堆栈段基址0x40000000限长0x2FFFFDPL33. 段、选择子与对象、句柄的关系在编程语言中段和选择子与对象和句柄的概念有一定的相似性但本质不同。段Segment vs 对象Object段是内存区域由描述符定义包括基址、限长、属性等。段是物理内存或线性地址空间的一块区域。对象在操作系统中对象是一个抽象的数据结构表示系统资源如文件、线程、窗口等。对象通常由内核管理并可能有复杂的操作和行为。选择子Selector vs 句柄Handle选择子是一个16位的数值用于索引GDT或LDT中的描述符。选择子本身不包含资源信息只是描述符表的索引。句柄通常是一个整数值用于标识一个内核对象。句柄是进程相关的在用户态句柄是访问内核对象的标识。句柄可以看作是一个指向内核对象表的索引。类比说明将描述符表GDT/LDT比作对象表内核对象表。描述符Descriptor比作对象表示一个段。选择子Selector比作句柄用于访问对象。但是这种类比并不完全准确因为描述符表是CPU硬件概念而对象表是操作系统软件概念。选择子直接索引描述符而句柄通常需要经过更复杂的转换才能找到内核对象。描述符描述的是内存段而内核对象可以代表各种资源。核心对象Kernel Objects在Windows中核心对象或称内核对象是由操作系统内核创建和管理的数据结构用于表示系统资源如进程、线程、文件、事件、信号量等。每个内核对象都有一个安全描述符和一组属性。用户态代码通过句柄来操作内核对象。编程语言中的段和选择子在现代操作系统中应用程序通常不直接操作段和选择子因为操作系统使用平坦内存模型使得段基址为0限长为4GB从而应用程序看到的线性地址空间是连续的。因此在编程语言中我们通常使用指针线性地址来访问内存而不需要关心段和选择子。然而在系统编程中如编写操作系统内核或驱动程序仍然需要设置GDT和LDT。以下是一个简单的示例展示如何用汇编语言定义GDT和LDT。示例定义GDT和LDTassembly; 假设我们使用汇编语言如NASM定义GDT和LDT; GDT定义gdt_start:dq 0x0000000000000000 ; 空描述符; 内核代码段索引1 dw 0xFFFF ; 限长低16位 dw 0x0000 ; 基址低16位 db 0x00 ; 基址中间8位 db 0x9A ; 访问权限P1, DPL0, S1, Type1010执行/读 db 0xCF ; 标志G1, D1, 限长高4位0xF db 0x00 ; 基址高8位 ; 内核数据段索引2 dw 0xFFFF dw 0x0000 db 0x00 db 0x92 ; 访问权限P1, DPL0, S1, Type0010读/写 db 0xCF db 0x00 ; 进程A的LDT描述符索引5 dw ldt_a_limit ; LDT_A的限长假设为24字节3个描述符 dw ldt_a_base ; LDT_A的基址低16位 db ldt_a_base 16 ; 基址中间8位 db 0x82 ; 访问权限P1, DPL0, S0, Type0010LDT db 0x00 ; 标志G0, 保留位 db 0x00 ; 基址高8位 ; 进程A的TSS描述符索引6 dw tss_a_limit ; TSS_A的限长假设为104字节 dw tss_a_base ; TSS_A的基址低16位 db tss_a_base 16 db 0x89 ; 访问权限P1, DPL0, S0, Type1001可用TSS db 0x00 db 0x00 ; 进程B的LDT描述符索引7 dw ldt_b_limit dw ldt_b_base db ldt_b_base 16 db 0x82 db 0x00 db 0x00 ; 进程B的TSS描述符索引8 dw tss_b_limit dw tss_b_base db tss_b_base 16 db 0x89 db 0x00 db 0x00gdt_end:; 定义GDT指针用于lgdt指令gdt_descriptor:dw gdt_end - gdt_start - 1 ; GDT限长dd gdt_start ; GDT基址; 进程A的LDT定义ldt_a_start:; 进程A代码段LDT索引0dw 0x3FFFF ; 限长低16位0x3FFFF256KB-1dw 0x0000 ; 基址低16位0x00400000db 0x40 ; 基址中间8位0x40db 0xFA ; 访问权限P1, DPL3, S1, Type1010执行/读db 0xCF ; 标志G1, D1, 限长高4位0x3db 0x00 ; 基址高8位0x00; 进程A数据段LDT索引1 dw 0x7FFFF ; 0x7FFFF512KB-1 dw 0x0000 ; 基址0x00800000 db 0x80 db 0xF2 ; 访问权限P1, DPL3, S1, Type0010读/写 db 0xCF db 0x00 ; 进程A堆栈段LDT索引2 dw 0x1FFFF ; 0x1FFFF128KB-1 dw 0x0000 ; 基址0x00C00000 db 0xC0 db 0xF6 ; 访问权限P1, DPL3, S1, Type0110读/写/向下扩展 db 0xCF db 0x00ldt_a_end:ldt_a_limit equ ldt_a_end - ldt_a_start - 1ldt_a_base equ ldt_a_start; 进程B的LDT定义类似但基址和限长不同ldt_b_start:; 进程B代码段dw 0x5FFFF ; 0x5FFFF384KB-1dw 0x0000 ; 基址0x20000000db 0x00db 0x20 ; 基址中间8位0x20注意0x20000000的中间8位是0x00高8位是0x20db 0xFAdb 0xCFdb 0x20 ; 基址高8位0x20; 进程B数据段 dw 0x9FFFF ; 0x9FFFF640KB-1 dw 0x0000 ; 基址0x30000000 db 0x00 db 0x30 db 0xF2 db 0xCF db 0x30 ; 进程B堆栈段 dw 0x2FFFF ; 0x2FFFF192KB-1 dw 0x0000 ; 基址0x40000000 db 0x00 db 0x40 db 0xF6 db 0xCF db 0x40ldt_b_end:ldt_b_limit equ ldt_b_end - ldt_b_start - 1ldt_b_base equ ldt_b_start; TSS定义简化这里不展开tss_a_start:; 进程A的TSS至少104字节resb 104tss_a_end:tss_a_limit equ tss_a_end - tss_a_start - 1tss_a_base equ tss_a_starttss_b_start:resb 104tss_b_end:tss_b_limit equ tss_b_end - tss_b_start - 1tss_b_base equ tss_b_start5. 总结GDT全局描述符表包含系统段描述符和各个进程的LDT描述符、TSS描述符。LDT局部描述符表进程私有包含进程的代码段、数据段、堆栈段等描述符。段由描述符定义的内存区域。选择子用于索引描述符表的16位值包含索引、TI表指示器和RPL请求特权级。对象和句柄在操作系统中内核对象是系统资源的抽象句柄是访问内核对象的标识。与段和选择子有相似之处但层次不同。现代Windows使用平坦内存模型因此应用程序通常不感知段的存在。但在操作系统内核中GDT和LDT如果使用仍然需要正确设置以支持多任务和内存保护。Windows系统中GDT和LDT的详细结构与编程映射我将深入解析GDT/LDT描述符的结构并通过一个三进程的例子说明它们在编程中与对象/句柄的对应关系。1.GDT和LDT描述符的具体结构标准描述符格式8字节/64位位域分布 63 56 55 52 51 48 47 40 39 32 ┌──────────┬────┬────┬──────────┬─────────────┐ │ Base[31:24] │ G │ D │ Access │ Base[23:16] │ ├──────────┼────┼────┼──────────┼─────────────┤ 31 24 23 20 19 16 15 8 7 0 ├──────────┼────┼────┼──────────┼─────────────┤ │ Base[15:0] │ Limit[15:0] │ Limit[19:16]│ └──────────┴────┴────┴──────────┴─────────────┘详细字段解析A. 访问权限字节第5字节// 第5字节结构位7-0位:76543210├─┼───┼─┼──────┤ P DPL S TYPE#defineSEGMENT_DESCRIPTOR_ACCESS\/* 位7: Present */\P:1,/* 1段存在0段不存在引发#NP异常 */\/* 位6-5: Descriptor Privilege Level */\DPL:2,/* 00Ring0, 01Ring1, 10Ring2, 11Ring3 */\/* 位4: Segment Descriptor */\S:1,/* 1代码/数据段0系统段/门描述符 */\/* 位3-0: Type */\TYPE:4/* 具体含义取决于S位 */B. TYPE字段的具体含义// 当S1时代码/数据段数据段TYPE:代码段TYPE:0000:只读1000:只执行0001:只读/已访问1001:只执行/已访问0010:读/写1010:执行/读0011:读/写/已访问1011:执行/读/已访问0100:只读/向下扩展1100:只执行/一致0101:读/写/向下扩展1101:只执行/一致/已访问0110:读/写/向下扩展/已访问1110:执行/读/一致0111:读/写/向下扩展/已访问1111:执行/读/一致/已访问// 当S0时系统段0001:可用TSS16位1001:可用TSS32位0010:LDT描述符1010:保留0011:忙TSS16位1011:忙TSS32位0100:调用门16位1100:调用门32位0101:任务门1101:保留0110:中断门16位1110:中断门32位0111:陷阱门16位1111:陷阱门32位2.三进程场景的详细实例假设我们有三个进程System系统进程Ring 0Process A用户进程Ring 3Process B用户进程Ring 3进程的内存布局// 物理地址空间布局简化0x00000000-0x000FFFFF:系统内核1MB0x00100000-0x0010FFFF:进程A代码段64KB0x00110000-0x0011FFFF:进程A数据段64KB0x00120000-0x0012FFFF:进程A堆栈段64KB0x00200000-0x0020FFFF:进程B代码段64KB0x00210000-0x0021FFFF:进程B数据段64KB0x00220000-0x0022FFFF:进程B堆栈段64KB0x00300000-0x0030FFFF:共享内存区64KB3.GDT具体结构完整示例GDT条目定义; GDT定义 gdt_start: ; 索引0: 空描述符必须为0 gdt_null: dd 0x00000000 dd 0x00000000 ; 索引1: 内核代码段选择子0x08 gdt_kernel_code: dw 0xFFFF ; 限长15:0 (0xFFFF) dw 0x0000 ; 基址15:0 (0x00000000) db 0x00 ; 基址23:16 (0x00) db 0x9A ; 访问权限: P1, DPL00, S1, TYPE1010(执行/读) db 0xCF ; 标志: G1(4KB), D1(32位), Limit[19:16]0xF db 0x00 ; 基址31:24 (0x00) ; 完整值: 0x00CF9A000000FFFF ; 含义: 基址0x00000000, 限长0xFFFFF*4KB4GB, DPL0 ; 索引2: 内核数据段选择子0x10 gdt_kernel_data: dw 0xFFFF dw 0x0000 db 0x00 db 0x92 ; TYPE0010(读/写) db 0xCF db 0x00 ; 0x00CF92000000FFFF ; 索引3: 用户代码段模板选择子0x18 gdt_user_code: dw 0xFFFF dw 0x0000 db 0x00 db 0xFA ; P1, DPL11(3), S1, TYPE1010 db 0xCF db 0x00 ; 0x00CFFA000000FFFF ; 索引4: 用户数据段模板选择子0x20 gdt_user_data: dw 0xFFFF dw 0x0000 db 0x00 db 0xF2 ; P1, DPL11, S1, TYPE0010 db 0xCF db 0x00 ; 0x00CFF2000000FFFF ; 索引5: 进程A的LDT描述符选择子0x28 gdt_ldt_a: dw ldt_a_limit ; LDT_A的限长 dw ldt_a_base_low db ldt_a_base_mid db 0x82 ; P1, DPL00, S0, TYPE0010(LDT) db 0x00 ; G0(字节粒度) db ldt_a_base_high ; 假设LDT_A在0x1000, 大小0x100 ; 索引6: 进程A的TSS描述符选择子0x30 gdt_tss_a: dw tss_a_limit ; TSS大小-1 (通常0x67103字节) dw tss_a_base_low db tss_a_base_mid db 0x89 ; P1, DPL00, S0, TYPE1001(32位可用TSS) db 0x00 db tss_a_base_high ; 假设TSS_A在0x2000 ; 索引7: 进程B的LDT描述符选择子0x38 gdt_ldt_b: dw ldt_b_limit dw ldt_b_base_low db ldt_b_base_mid db 0x82 db 0x00 db ldt_b_base_high ; 假设LDT_B在0x3000 ; 索引8: 进程B的TSS描述符选择子0x40 gdt_tss_b: dw tss_b_limit dw tss_b_base_low db tss_b_base_mid db 0x89 db 0x00 db tss_b_base_high ; 假设TSS_B在0x4000 ; 索引9: 系统进程LDT选择子0x48 gdt_ldt_system: dw ldt_system_limit dw ldt_system_base_low db ldt_system_base_mid db 0x82 db 0x00 db ldt_system_base_high ; 索引10: 系统进程TSS选择子0x50 gdt_tss_system: dw tss_system_limit dw tss_system_base_low db tss_system_base_mid db 0x89 db 0x00 db tss_system_base_high ; 索引11: 调用门选择子0x58 gdt_call_gate: dw syscall_offset_low ; 系统调用处理函数偏移15:0 dw 0x0008 ; 目标代码段选择子内核代码段 db 0x00 ; 参数计数0 db 0xEC ; P1, DPL11, TYPE1100(32位调用门) dw syscall_offset_high ; 偏移31:16 ; 允许用户态调用内核函数 gdt_end:4.LDT具体结构进程A的LDT基址0x1000; 进程A的LDT ldt_a_start: ; 索引0: 进程A代码段选择子0x07: TI1, RPL3 ldt_a_code: dw 0xFFFF ; 限长0xFFFF64KB-1 dw 0x0000 ; 基址15:00x0000 db 0x10 ; 基址23:160x10 (基址0x00100000) db 0xFA ; P1, DPL11, S1, TYPE1010(执行/读) db 0x40 ; G0(字节粒度), D1, Limit[19:16]0 db 0x00 ; 基址31:240x00 ; 完整: 基址0x00100000, 限长0xFFFF(64KB) ; 索引1: 进程A数据段选择子0x0F ldt_a_data: dw 0xFFFF ; 限长0xFFFF dw 0x0000 ; 基址15:00x0000 db 0x11 ; 基址23:160x11 (基址0x00110000) db 0xF2 ; P1, DPL11, S1, TYPE0010(读/写) db 0x40 db 0x00 ; 基址0x00110000, 限长0xFFFF ; 索引2: 进程A堆栈段选择子0x17 ldt_a_stack: dw 0xFFFF ; 限长0xFFFF dw 0x0000 ; 基址15:00x0000 db 0x12 ; 基址23:160x12 (基址0x00120000) db 0xF6 ; P1, DPL11, S1, TYPE0110(读/写/向下扩展) db 0x40 db 0x00 ; 基址0x00120000, 限长0xFFFF ; 索引3: 进程A共享内存段选择子0x1F ldt_a_shared: dw 0xFFFF ; 限长0xFFFF dw 0x0000 ; 基址15:00x0000 db 0x30 ; 基址23:160x30 (基址0x00300000) db 0xF2 ; P1, DPL11, TYPE0010 db 0x40 db 0x00 ; 基址0x00300000 ldt_a_end: ldt_a_limit equ ldt_a_end - ldt_a_start - 1进程B的LDT基址0x3000; 进程B的LDT ldt_b_start: ; 索引0: 进程B代码段选择子0x07 ldt_b_code: dw 0xFFFF ; 限长0xFFFF dw 0x0000 ; 基址15:00x0000 db 0x20 ; 基址23:160x20 (基址0x00200000) db 0xFA ; P1, DPL11, TYPE1010 db 0x40 db 0x00 ; 基址0x00200000 ; 索引1: 进程B数据段选择子0x0F ldt_b_data: dw 0xFFFF dw 0x0000 db 0x21 ; 基址23:160x21 (基址0x00210000) db 0xF2 ; TYPE0010 db 0x40 db 0x00 ; 索引2: 进程B堆栈段选择子0x17 ldt_b_stack: dw 0xFFFF dw 0x0000 db 0x22 ; 基址23:160x22 (基址0x00220000) db 0xF6 ; TYPE0110 db 0x40 db 0x00 ; 索引3: 进程B共享内存段选择子0x1F ldt_b_shared: dw 0xFFFF dw 0x0000 db 0x30 ; 基址23:160x30 (基址0x00300000与进程A共享) db 0xF2 ; TYPE0010 db 0x40 db 0x00 ldt_b_end: ldt_b_limit equ ldt_b_end - ldt_b_start - 15.段/选择子 vs 对象/句柄的对应关系概念映射表硬件机制 (CPU层) ↔ 软件抽象 (OS层) ────────────────────────────────────────────────── 描述符 (Descriptor) ↔ 对象 (Object) 描述符表 (GDT/LDT) ↔ 对象管理器/句柄表 选择子 (Selector) ↔ 句柄 (Handle) 段寄存器 (Segment Reg) ↔ 句柄缓存/对象引用 GDTR/LDTR ↔ 对象表指针 段 (内存区域) ↔ 资源 (Resource) TSS (任务状态段) ↔ 进程/线程对象 调用门 (Call Gate) ↔ 系统调用API实际编程中的对应关系// Windows API中的句柄使用HANDLE hProcessCreateProcess(...);// 创建进程对象HANDLE hFileCreateFile(...);// 创建文件对象HANDLE hMutexCreateMutex(...);// 创建互斥体对象// 类似地在分段模型中USHORT hCodeSeg0x0007;// LDT中的代码段选择子TI1, RPL3USHORT hDataSeg0x000F;// LDT中的数据段选择子USHORT hStackSeg0x0017;// LDT中的堆栈段选择子// 使用选择子访问内存__asm{mov ax,hDataSeg// 加载数据段选择子类似获取句柄mov ds,ax// 设置DS段寄存器类似绑定句柄到上下文mov eax,[ebx]// 访问内存通过句柄访问资源}核心对象Kernel Objects的概念在Windows中核心对象是操作系统内核管理的、代表系统资源的抽象数据结构// 核心对象类型示例不完全列表typedefstruct_OBJECT_TYPE{UNICODE_STRING Name;// 对象类型名OBJECT_TYPE_INITIALIZER TypeInfo;// ...}OBJECT_TYPE;// 常见的核心对象// 1. 进程对象 (EPROCESS)// 2. 线程对象 (ETHREAD)// 3. 文件对象 (FILE_OBJECT)// 4. 事件对象 (KEVENT)// 5. 信号量对象 (KSEMAPHORE)// 6. 互斥体对象 (KMUTEX)// 7. 内存区域对象 (SECTION_OBJECT)// 对象与句柄的关系User Space:Handle(句柄)→ 索引 → Kernel Object Table → KernelObject(e.g.,0x44)(每个进程私有)(e.g.,File Object)与分段模型的类比代码// 分段模型中的对象管理器structSEGMENT_OBJECT{DWORD BaseAddress;// 段基址DWORD Limit;// 段限长BYTE Attributes;// 段属性DWORD ReferenceCount;// 引用计数// ...};// GDT/LDT相当于对象表structDESCRIPTOR_TABLE{SEGMENT_OBJECT Objects[8192];// GDT最大8192个条目DWORD Count;// 已用条目数DWORD BaseAddress;// 表基址};// 选择子相当于句柄typedefstruct_SELECTOR{WORD Index:13;// 索引类似句柄值WORD TI:1;// 表指示器0GDT, 1LDTWORD RPL:2;// 请求特权级}SELECTOR;// 使用示例SELECTORAllocateSegment(DWORD base,DWORD limit,BYTE attr){// 在GDT/LDT中分配一个描述符类似创建内核对象intindexFindFreeDescriptorSlot();GDT[index].BaseAddressbase;GDT[index].Limitlimit;GDT[index].Attributesattr;SELECTOR selector;selector.Indexindex;selector.TI0;// GDTselector.RPL3;// 用户态returnselector;// 返回句柄}// 使用句柄访问资源voidAccessMemory(SELECTOR seg,DWORD offset,BYTE*data){// 类似通过句柄访问内核对象if(seg.TI0){DESCRIPTOR descGDT[seg.Index];// 通过句柄查找对象if(offsetdesc.Limit){BYTE*ptr(BYTE*)desc.BaseAddressoffset;*data*ptr;// 访问资源}}}6.现代Windows的实现平坦模型虽然Windows主要使用平坦模型但GDT仍然存在// 现代Windows GDT典型布局32位系统typedefstruct_KGDTENTRY{WORD LimitLow;WORD BaseLow;union{struct{BYTE BaseMid;BYTE Flags1;// Type, DPL, PBYTE Flags2;// LimitHigh, AVL, etc.BYTE BaseHi;}Bytes;struct{DWORD BaseMid:8;DWORD Type:5;DWORD Dpl:2;DWORD Pres:1;DWORD LimitHi:4;DWORD Sys:1;// 0系统段, 1代码/数据段DWORD Reserved_0:1;DWORD Default_Big:1;DWORD Granularity:1;DWORD BaseHi:8;}Bits;}HighWord;}KGDTENTRY;// Windows GDT布局简化KGDTENTRY GdtEntries[]{// 索引0: 空描述符{0,0,{0,0,0,0}},// 索引1: 内核代码段 (0x08){0xFFFF,0,{0,0x9A,0xCF,0}},// 基址0, 限长4GB, DPL0// 索引2: 内核数据段 (0x10){0xFFFF,0,{0,0x92,0xCF,0}},// 基址0, 限长4GB, DPL0// 索引3: 用户代码段 (0x1B) - 注意RPL3所以选择子0x18|30x1B{0xFFFF,0,{0,0xFA,0xCF,0}},// 基址0, 限长4GB, DPL3// 索引4: 用户数据段 (0x23){0xFFFF,0,{0,0xF2,0xCF,0}},// 基址0, 限长4GB, DPL3// 索引5: TSS段 (每个CPU一个){sizeof(TSS)-1,TSS_BASE_LOW,{TSS_BASE_MID,0x89,0x40,TSS_BASE_HIGH}},// 索引6: PCR处理器控制区域通过FS/GS访问{0xFFF,PCR_BASE_LOW,{PCR_BASE_MID,0x92,0x40,PCR_BASE_HIGH}},};// FS/GS的特殊用法// Windows使用FS在用户态访问TEB在内核态访问PCR__asm{mov eax,fs:[0x18]// 用户态: 获取TEBmov eax,gs:[0x0]// 内核态: 获取PCR}核心要点总结段 ↔ 对象都代表系统资源内存、文件等描述符 ↔ 对象定义描述资源的属性位置、大小、权限等选择子 ↔ 句柄都是资源的引用标识符GDT/LDT ↔ 对象表存储资源定义的容器核心对象Windows内核管理的、有状态的、可共享的系统资源抽象关键差异选择子是硬件机制直接由CPU解释句柄是软件抽象需要操作系统转换描述符表是固定结构由CPU架构定义对象管理器是灵活框架可扩展和动态管理这种类比有助于理解操作系统的资源管理哲学无论是硬件层的段还是软件层的对象其核心思想都是通过间接引用选择子/句柄来访问受管理的资源段/对象从而实现隔离、保护和资源共享。