网站建设伍金手指下拉7,茂名营销型网站制作公司,广州安全教育平台登录入囗,赣州百姓网免费发布信息网说明:S16 表示 16 位段寄存器P16 表示 16 位的普通寄存器, 立即数, 结果为 16 位的表达式等等.P32 同上, 只是扩展到 32 位.一. CPU 概况1. 8086: 8 位数据线, 16 位地址线. 8 位数据线和前8位地址线合用.2. 8088: 16位数据线, 16位地址线. 数据线和地址线完全分时合用.3. 8018…说明:S16 表示 16 位段寄存器P16 表示 16 位的普通寄存器, 立即数, 结果为 16 位的表达式等等.P32 同上, 只是扩展到 32 位.一. CPU 概况1. 8086: 8 位数据线, 16 位地址线. 8 位数据线和前8位地址线合用.2. 8088: 16位数据线, 16位地址线. 数据线和地址线完全分时合用.3. 80186: 16位数据线, 16位地址线. 数据线和地址线完全分时合用.4: 80188: 16位数据线, 16位地址线. 数据线和地址线完全分时合用.5. 80286: 16位数据线, 24位地址线. 数据线和地址线是完全分开的. 转到保护模式的过渡 CPU.6. 80386: 32位数据线, 32位地址线. 数据线和地址线是完全分开的(其中80386SX像80286).7. 80486: 32位数据线, 32位地址线.8. Pentium: 64位数据线, 32位地址线.9. Pentium Pro: 64位数据线, 36位地址线.二. 实模式: 分段内存1. 支持的 CPU: 8086 以上2. 启用方式: 启动后自动进入3. 地址长度: 204. 寻址能力: 1M5. ALU宽度: 166. 寻址过程:引入了 CS, DS, SS, ES 这 4 个 16 位的段寄存器. 寻址时将段寄存器左移 4 位后再加上 16 位的偏移, 既: (S16 4) P16. 得到 20 位的地址.省略段寄存器时, 会使用默认的段寄存器:段偏移用途CSIP指令地址DSAX, BX, SI, DI, Disp8/16数据地址SSSP, BP堆栈地址ESDI串操作目的地址三. 保护模式: 分段内存1. 支持的 CPU: 80286 以上2. 启用方式: 将 CR0 寄存器的 PE 位置 1.3. 地址长度: 324. 寻址能力: 4GB5. ALU宽度: 326. 寻址过程:从 32 位的数据宽度, 寻 32 位的地址, 看起来似乎是非常简单的一件事情. 不过由于对内存保护的加入, 这个过程其实更为复杂. 而 Intel 又选择了兼容之前的分段内存, 且分段机制在进入保护模式后是必须的, 不能关闭. 其实大多数的操作系统实现的时候都选择绕过分段机制, 只使用分页机制来进行内存管理.保护模式的分段机制保留了以前的段寄存器, 并且增加了两个 FS, GS. 这些段寄存器仍然为 16 位, 但是里面保存的不再是段的基地址了, 而是一个段选择子, 段选择子是一个如下的结构:struct SegSelector {unsigned int RPL : 2;unsigned int PI : 1;unsigned int Selector : 13;};既, 0-1 位表示请求的权限, 共有 0 - 3 四种. 但几乎所有的操作系统都只使用 2 种. 0 表示内核的, 3 表示用户空间的. 第 2 位决定是使用 GDT 还是 LDT, 为 0 使用 GDT, 为 1 使用 LDT. 选择绕过分段机制的操作系统是不会创建 LDT 的, 永远只使用 GDT. 最后高 13 位表示在 GDT/LDT 中的索引号.GDT/LDT 是段描述符的数组, 段描述符是描述段的基址, 边界, 属性的一个结构, 共 64 bit, 8 个字节. GDT 是全局的, 只有一个. LDT 可以有多个. Intel 设想的是, GDT 供操作系统内核使用, LDT 每个进程一个, 但是基本上没有人按这种方式来使用. 段描述符的结构如下:struct SegDesc {unsigned short limitLow;unsigned int baseLow : 24;unsigned int type : 4; // 根据 S 字段的不用, 有不同的含义. 包含读写权限等等.unsigned int S : 1; // 系统段标志, 为 0 表示系统段unsigned int DPL : 2; // 段的权限等级. 0 为内核 3 位用户unsigned int P : 1; // 段是否在内存中, 为 1 表示在内存. 当 P 为 0 时, base 和 limit 都是无效的, 操作系统可以用来保存自己的数据.unsigned int limitHigh : 4;unsigned int AVL : 1; // CPU 不使用, 软件自己决定表示什么.unsigned int zero : 1; // 为 0unsigned int DB : 1; // 根据段的使用方式, 有不同的含义.unsigned int G : 1; // 粒度, 决定 Limit 的单位. 为 0, 单位为字节. 为 1, 单位是 4KBunsigned char baseHigh;};之所以这么复杂, 是因为在 80286 中, 高 16 位是没有使用的. 新的 CPU 为了兼容这个过渡产品, base 和 limit 只能扩展到高 16 位去.GDT/LDT 这个数组是放在内存里面的, 所以还需要记录它们在内存中的起始位置, 为此, 又增加了 2 个寄存器: GDTR 和 LDTR. GDTR 是一个 48 位的寄存器, 高 32 位是一个线性地址, 低 16 位是边界. LDTR 是一个 16 位寄存器, 里面保存的是在 GDT 中的索引号.struct {unsigned short limit;unsigned int base;} GDTR;这样, 段寄存器通过查询 GDT/LDT 表获得段的基址后, 再加上偏移得到一个 32 位的地址. 这个地址被称为线性地址. 如果没有启用下面说的分页机制, 那么线性地址就是物理地址. 如果启用了分页机制, 线性地址还需要经过一次映射才能得到物理地址. 综上, 虚拟地址到线性地址的映射关系可用如下伪代码来描述:if(S16 0x04 0) // 取段寄存器的第 3 位, 判断是使用 GDT 还是 LDT{ // 使用 GDTgdt (GDTR 16) 0xFFFFFFFF; // 取 GDTR 寄存器的高 32 位, 既 GDT 表的起始地址.sd gdt S16 0xFFF8; // 根据段寄存器中的索引号找到段描述符sbase_l (sd 12) 0x00FFFFFF; // 取基址的低 24 位sbase_h (sd 32) 0xFF000000; // 取基地址高 8 位sbase sbase_h | sbase_l;return sbase P32 // 基址加上偏移得到最终的线性地址}else{ // 使用 LDTgdt (GDTR 16) 0xFFFFFFFF;sd_ldt gdt LDTR 0xFFF8;ldt (sd_ldt 12) 0x00FFFFFF (sd_ldt 32) 0xFF000000;sd ldt S16 0xFFF8;sbase (sd 12) 0x00FFFFFF (sd 32) 0xFF000000;return sbase P32;}或者, 我们使用上面定义的结构来表述:if(SegSelector(S16)-PI){ // PI 为 1 使用 LDTSegDesc* gdt GDTR-base;SegDesc* ldt gdt[LDTR 3];SegDesc* sd ldt[SegSelector(S16)-Selector];void* base sd-baseHigh 24 sd-baseLow;return base P32}else{ // PI 为 0 使用 GDTSegDesc* gdt GDTR-base;SegDesc* sd gdt[SegSelector(S16)-Selector];void* base sd-baseHigh 24 sd-baseLow;return base P32}同样, 在没有指明段寄存器的情况下, 会使用一个默认的段寄存器:段偏移用途CSEIP指令地址DSEAX, EBX, ECX, EDX, ESI, EDI, Disp8/16/32数据地址SSESP, EBP堆栈地址ESEDI串操作目的地址GS无一般地址FS无一般地址以下是网上搜集的描述分段内存的图表:四. 保护模式: 分页内存1. 支持的 CPU: 80386 以上, PSE 需要 Pentium 以上2. 启用方式: 将 CR0 寄存器的 PG 位置 13. 地址长度: 324. 寻址能力: 4GB5. ALU宽度: 326. 寻址过程:分页机制是现代操作系统实现内存管理的主要方式. 它将线性地址空间划分为固定大小的页面, 每个页面可以被映射到物理内存或外部存储器的虚拟内存文件中, 并且进行权限检查. 在没有启用 PAE 时, 内存页面大小可以是 4KB 或 4MB. 如果 CR4 中的 PSE 位是 0, 则只支持 4KB 的内存页. 如果 PSE 位是 1, 则根据 PDE 中的 PS 位来决定内存页的大小.1# 4KB 页面寻址对于 4KB 的页面, 32 位的线性地址不再表示物理地址, 而是变成如下的含义了:struct LineAddress {unsigned int offset : 12;unsigned int table : 10;unsigned int directory : 10;};其中高 10 位表示页目录的下标, 中间 10 位表示页表中的下标. 在系统中, 每一个进程有一个页目录, 其基址为 4KB 对齐, 低 12 位为 0, 高 20 位存放在 CR3 寄存器中的高 20 位里. 因此, CR3 寄存器又被称为页目录基址寄存器(PDBR). CR3 的结构为:struct CR3 {unsigned int nouse1 : 3;unsigned int PWT : 1; // Page Write Through 标志, CR0.CD 为 1 时忽略, CR0.CD 为 0 时: PWT 1 使用 Write-Through 的缓存类型, PWT 0 使用 Write-Back 的缓存类型.unsigned int PCD : 1; // Page Cache Disable 标志, CR0.CD 为 1 时忽略, CR0.CD 为 0 时: PCD 1 表示该物理页不能被缓存unsigned int nouse2 : 7;unsigned int pdt_base : 20;};页目录(Page Directory)是一个 4KB 大小的数组, 里面包含 1024 个 4 字节的页目录表项(PDE, Page Directory Entry). 对于 4KB 的页面, PDE 的结构如下:struct PDE {unsigned int P : 1; // Present, 是否在物理内存中, 1 在, 0 不在unsigned int R/W: 1; // Read/Write, 为 1 表示可读写, 为 0 表示只读unsigned int U/S : 1; // User/Supervisor 为 0 表示管理权限, 为 1 表示用户权限unsigned int PWT: 1; // Write-throughunsigned int PCD : 1; // Cashe-Disabledunsigned int A : 1; // Accessed 是否被访问过, 1 表示访问过unsinged int ZERO: 1; // 固定为 0unsigned int PS : 1; // PageSize, 页大小, 0 表示 4KB, 1 表示 4MB. 当 CR4 的 PSE 为 0 时, 忽略该项, 页大小始终为 4KB.unsigned int G : 1; // Global Page, 全局页.unsigned int nouse : 3; // CPU 未使用, 供系统程序员使用.unsigned int base : 20; // 页表基址的高 20 位, 低 12 位固定为 0. 所以, 页表基址一定是按 4KB 对齐的.};PDE 中最重要的, 是高 20 位表示的页表基址, 它指向的是一个 4KB 的页表(Page Table), 页表包含了 1024 个 4 字节的页表表项(Page Table Entry, PTE). PTE 的结构如下:struct PTE {unsigned int P : 1;unsinged int R/W : 1;unsigned int U/S : 1;unsigned int PWT: 1;unsigned int PCD : 1;unsigned int A : 1;unsigned int D : 1; // Dirty 表示内存页是否被修改过, 1 修改过 0 未修改过unsigned int PAT : 1; // Page Attribute Table, 在全局属性表中的索引unsigned int G : 1; // 全局页unsigned int nouse : 3; // 供系统程序员使用unsigned int base : 20; // 内存页起始物理地址的高 20 位, 低 12 位固定为 0, 所以必须按 4KB 对齐.};根据上面的结构, 线性地址到物理地址的映射过程, 可以用如下伪代码来表示:LineAddress laddr P32;PDE* pde CR3.pdt_base 12;PTE* pte pde[laddr.direcotry].base 12;char* pageStart pte[laddr.table].base 12;return pageStart laddr.offset;2# 4MB 页面寻址 (PSE 模式)对于 4MB 的页面, 不需要使用页表, 只需要页目录的一层映射. 要配置 4MB 的页面, 需要设置 CR4 中的 PSE 位. 并在 PDE 中设置 PS 位. 使用 4MB 页面时, 线性地址的结构如下:struct LineAddress {unsigned int offset : 22;unsigned int directory : 10;};此时的 PDE 结构如下:struct PDE {/* 0 */unsigned int P : 1;/* 1 */unsinged int R/W : 1;/* 2 */unsigned int U/S : 1;/* 3 */unsigned int PWT: 1;/* 4 */unsigned int PCD : 1;/* 5 */unsigned int A : 1;/* 6 */unsigned int D : 1;/* 7 */unsigned int PS : 1; // 4MB 页面该位为 1/* 8 */unsigned int G : 1;/* 9-11 */unsigned int nouse : 3; // 供系统程序员使用/* 12 */unsigned int PAT : 1;/* 13-21 */unsigned int reserved : 9; // 保留未使用, 必须为 0/* 22-31 */unsigned int base : 10; // 内存页起始物理地址的高 10 位, 低 22 位固定为 0, 所以必须按 4MB 对齐.};此时的寻址过程伪代码如下:LineAddress laddr P32;PDE* pde CR3.pdt_base 12;char* pageStart pde[laddr.direcotry].base 22;return pageStart laddr.offset;以下是网上搜集的描述分页内存的图表:1. 内存的二级分页结构2. 4KB 页面寻址过程3. 4MB 页面寻址过程五. 虚拟 86 模式 (V8086, V86)1. 支持的 CPU: 80386 以上2. 启用方式: 在保护模式下, 将标志寄存器中的 VM 位置 13. 地址长度: 204. 寻址能力: 1MB5. ALU 宽度: 166. 寻址过程:虚拟 86 模式是保护模式下, 某些任务的一种工作模式. 此模式是为了能够在保护模式下运行实模式软件. 在虚拟 86 模式下, 软件的工作环境和实模式类似, 使用 (S16 4) P16 的方式访问 1M 的内存, 但是得到的地址不再是物理地址了, 而是由系统的虚拟 86 管理程序分配的内存. 虚拟 86 模式下也可以使用内存分页(实模式下不行), 让没有使用的内存空间不占用物理内存. 虚拟 86 模式下的中断和特殊指令的访问也由系统软件进行模拟, 不能直接访问硬件.在虚拟 86 模式下, 是不能直接更改标志寄存器的 VM 位的, 所以进入和退出虚拟 86 模式是通过任务切换或中断来完成的.以下是网上搜集的描述 V86 模式的相关图表:1. 保护模式和 V86 模式的切换六. PSE-36: Page Size Extension 361. 支持的 CPU: Pentium III 以上 (另说为 Pentium II)2. 启用方式: 开启 PSE 的情况下, 如果 CPU 支持即可使用3. 地址长度: 364. 寻址能力: 64GB5. ALU 宽度: 326. 寻址过程:在前面的分页内存中, 处于 PSE 模式时, PDE 结构只使用了高 10 位作为基址. 在 PSE-36 模式里, 将使用其中的 14 位来作为基址, 这样, 最后的地址位数将达到 36 位, 寻址能力提高到 64GB. 在 PSE 36 模式下, 4MB 页面的 PDE 结构变为:struct PDE {/* 0 */unsigned int P : 1;/* 1 */unsinged int R/W : 1;/* 2 */unsigned int U/S : 1;/* 3 */unsigned int PWT: 1;/* 4 */unsigned int PCD : 1;/* 5 */unsigned int A : 1;/* 6 */unsigned int D : 1;/* 7 */unsigned int PS : 1; // 4MB 页面该位为 1/* 8 */unsigned int G : 1;/* 9-11 */unsigned int nouse : 3; // 供系统程序员使用/* 12 */unsigned int PAT : 1;/* 13-16 */unsigned int baseHigh : 4; // 内存起始地址的 32-35 位/* 17-21 */unsigned int reserved : 5; // 保留未使用, 必须为 0/* 22-31 */unsigned int baseLow : 10; // 内存页起始物理地址的 22-31 位.};此时寻址过程伪代码为:LineAddress laddr P32;PDE* pde CR3.pdt_base 12;INT64 pageStart (INT6)pde[laddr.direcotry].baseLow 22 (INT64)pde[laddr.directory].baseHigh 32;return pageStart laddr.offset;对于 4KB 的页面, 仍然和普通的分页内存相同, 它可以表示的内存仍然只要 4GB. 所以, 在 PSE 36 模式下, 4KB 的页面只能位于前 4GB 物理内存中. 4GB 以上的内存只能通过 PSE 方式访问, 页面大小只能为 4MB.七. PAE: Physical Address Extension 物理地址扩展1. 支持的 CPU: Pentium Pro 以上2. 启用方式: 设置 CR4 中的 PAE 位3. 地址长度: 364. 寻址能力: 64GB5. ALU 宽度: 326. 寻址过程:在 PAE 模式中, 应用程序仍然为 32 位, 只能使用 4GB 的内存空间. 但是系统可以把不同的进程映射到 64GB 的物理内存中. 应用程序如果需要使用大于 4GB 的内存, 则需要操作系统的特殊支持(Windows 为 AWE, Address Windowing Extensions; Unix 存在多种, 比如 mmap ).启用 PAE 后, CR3 寄存器不再指向页目录基址, 而是指向一个页目录指针表 PDPT (Page Directory Pointer Table), 即包含 4 个页目录指针的表. 页目录项和页表项从原来的 4 字节变为 8 字节, 占用的内存大小仍然为 4KB, 所以其中的表项从 1024 个变为 512 个. 因此, 现在一共有 4 个页目录表, 页目录表和页表的下标也只需要 9 位了, 于是线性地址的划分也有了变化.1# 4KB 页面寻址在 4KB 页面下, 线性地址被描述为:struct LineAddress {unsigned int offset : 12;unsigned int table : 9;unsigned int directory : 9;unsigned int ptrindex : 2;};其中的高 2 位表示在页目录指针表 PDPT 内的索引, CR3 寄存器里保存了 PDPT 的地址, CR3 结构为:struct CR3 {unsigned int nouse : 5;unsigned int pdpt_base : 27;};因此, PDPT 的地址是 32 字节对齐的, 因为 PDPT 的大小是 32 字节. PDPT 的表项 PDPTE 是 64 位的, 下面是 PDPTE 的结构:struct PDPTE {unsigned int P : 1;unsigned int reseved1 : 2; // 保留, 必须为 0unsigned int PWT : 1;unsigned int PCD : 1;unsigned int reserved2 : 4; // 保留, 必须为 0unsigned int nouse : 3;unsigned int pdt_base : 52;};PDPTE 从第 12 位开始的高位是 PDT 的基地址的高位, 随着物理地址位数的不同, 使用的位也不同, 未使用的位需保持为 0. PDT 的低 12 位固定为 0, 按 4KB 对齐. 比如果物理地址是 52 位, 则 PDT 的高 40 位由 PDPTE[51:12] 提供, PDPTE[63:52] 必须为 0. 当物理地址是 40 位时, PDT[39:12] PDPTE[39:12], 物理地址 36 位时 PDT[35:12] PDPTE[35:12].PDE 在 PAE 模式下是 64 位了, 结构中的 PS 0 时表示 4 KB 的页面, 此时的 PDE 结构如下:struct PDE_4k {unsigned int P : 1;unsigned int R/W : 1;unsigned int U/S : 1;unsigned int PWD : 1;unsigned int PCD : 1;unsigned int A : 1;unsigned int nouse1 : 1; // 忽略unsigned int PS : 1; // 4KB 页面这里是 0unsigned int nouse2 : 4;unsigned int pt_base : 51; // PDT 的基址, 和 PDPTE 类似, 随着物理地址位数不同, 该结构中有效的位数也不同, 无效的位需要为 0unsigned int XD : 1; // Execution Disable: 当寄存器 IA32_EFER.NXE 置位后有效, 否则为保留必须为 0 的位. 开启 XD 功能后, PDE.XD 1 或 PTE.XD 1 则该页面是数据页, 不可执行.};PDE 中从第 12 位开始的高位表示 PT 的基地址, 随着物理地址的位数不同, 使用的 PDE 结构中的位数也不同. PT 基地址的低 12 位固定为 0, 以 4 KB 对齐. PT 中存放的 PTE 结构也是 64 位的了:struct PTE {unsigned int P : 1;unsigned int R/W : 1;unsigned int U/S : 1;unsigned int PWD : 1;unsigned int PCD : 1;unsigned int A : 1;unsigned int D : 1;unsigned int PAT : 1;unsigned int G : 1;unsigned int nouse : 3;unsigned int page_frame : 51; // 12~62 位是 4KB 页面的基地址了, 和 PDPTE 一样, 随着物理地址位数的不同, 有效位数不同.unsigned int XD : 1;};在上述扩展下, 寻址过程和 Non-PAE 模式下是类似的, 只是多了 PDPT 一个层次, 线性地址到物理地址转换的伪代码表示如下:LineAddress laddr P32;PDPTE* pdpt CR3.pdpt_base 5;PDE_4k* pde pdpt[laddr.ptrindex].pdt_base 12;PTE* pt pde[laddr.direcotry].pt_base 12;char* pageStart pt[laddr.table].page_frame 12;return pageStart laddr.offset;其中的指针类型的位数不再是 32 位, 可以认为是 64 位或物理地址的位数.2# 2MB 页面寻址在 PDE 中, PS 位是 1 的话, 将会使用 2MB 的页面, 由于不再使用 PTE 结构, 线性地址的含义如下:struct LineAddress {unsigned int offset : 21;unsigned int directory : 9;unsigned int ptrindex : 2;};CR3 以及 PDPTE 的结构都和 4KB 模式下相同, PDE 的结构有些区别:struct PDE_2M {unsigned int P : 1;unsigned int R/W : 1;unsigned int U/S : 1;unsigned int PWT : 1;unsigned int PCD : 1;unsigned int A : 1;unsigned int D : 1;unsigned int PS : 1 // 2M 页面该位是 1unsigned int G : 1;unsigned int nouse1 : 3;unsigned int PAT : 1;unsigned int reserved : 8; // 保留必须为 0unsigned int frame_base : 43; // 21~63, 随物理地址位数不同有效位不同, 无效的位必须为 0unsigned int XD : 1;};其中页面地址的低 21 位固定为 0, 基址按 2MB 对齐, 高位由 PDE_2M 的高位提供. 此时寻址过程如下:LineAddress laddr P32;PDPTE* pdpt CR3.pdpt_base 5;PDE_2M* pde pdpt[laddr.ptrindex].pdt_base 12;char* pageStart pde[laddr.directory].frame_base 21;return pageStart laddr.offset;附图:1. PAE 模式下 4KB 页面的寻址2. PAE 模式下 2MB 页面的寻址八. 长模式 (long-mode, IA-32e 模式)1. 支持的 CPU: x86-64 的 CPU2. 启用方式:同时满足以下条件:(1). 开启保护模式 CR0.PE 1(2). 开启分页机制 CR0.PG 1(3). 开启 PAE CR4.PAE 1(4). IA32_EFER.LME 1 (Long Mode Enable)(5). IA32_EFER.LMA 1 (Long Mode Active)3. 地址长度: 484. 寻址能力: 256 TB5. ALU 宽度: 646. 寻址过程:x86-64 体系, 也被称为 x64 体系, 还被叫做 AMD 64 和 Intel 64 体系. 他们是 x86 体系向 64 位的扩展, 有别于纯 64 位架构的 IA64 体系. x64 体系兼容 x86 的运行模式, 并增加一种新的长模式. x64 的运行模式如下:x64 体系子模式资源long-mode (IA-32e)64-bit mode64 位执行环境compatibility mode内核为 64 位, 应用为 32 位的 legacy modelegacy modeprotected mode32 位real mode16 位在长模式下, 内核只能为 64 位, 应用可以为 64 位或 32 位. 兼容模式(compatibility mode)和保护模式基本相同.在 64 位模式下, 寄存器被扩展为 64 位, 默认的地址大小也是 64 位(可以使用 67H 前缀来使用 32 位地址, 但是不能使用 16 位地址), 并增加了 RIP 相对寻址方式. 兼容模式下代码段描述符中的 D 标志位决定了默认的地址大小: D 0 默认为16位地址, D 1 默认为32位地址, 可通过 67H 前缀来改变默认值.1. 分段机制长模式下的分段机制被进一步的弱化, 但是仍然被保留下来.在 64 位模式下, 六个段寄存器仍然为 16 位, 其含义和保护模式下相同, 包含 Index, TI, RPL. 除 CS 寄存器外,其余寄存器允许加载 Null selector(SS 只能在 Ring 0/1/2 下加载 Null selector).GDTR/LDTR 的 base 扩展为 64 位, 所以 GDTR/LDTR 是 80 位的寄存器了:struct {unsigned short limit;unsigned int64 base;} GDTR;段描述符仍然为 8 字节 64 位, 但是里面的大多数字段都已经无效了. 因为在 64 位模式下, 只有 FS 和 GS 可以使用非 0 的段基址, 其余的段的基址都被固定为 0, 长度被固定为 0XFFFFFFFF. 对于 FS 和 GS 的段 base 值, 新增了两个 MSR 寄存器来表示, 分别是 IA32_FS_BASE, IA32_GS_BASE . 代码段的描述符格式如下:struct CodeSegDesc {0 - 15: unsigned short limitLow; // 无效16-39: unsigned int baseLow : 24; // 无效40: unsigned int A : 1; // 无效41: unsigned int R : 1; // 无效42: unsigned int C : 1;43: unsigned int C/D: 1; // 固定为 144: unsigned int S : 1; // 固定为 145-46: unsigned int DPL : 2;47: unsigned int P : 1;48-51: unsigned int limitHigh : 4; // 无效52: unsigned int AVL : 1; // 无效53: unsigned int L : 1;54: unsigned int D : 1;55: unsigned int G : 1; // 无效56-63: unsigned char baseHigh; // 无效};从上面可见, 64位模式下段描述符只有 C, DPL, P, L, D 五个可用的标志:C 代码一致性, 影响权限的检查DPL 标识段的权限P 段是否在内存中L 用于长模式下的子模式选择, L1 表示 64 位模式, L0 表示兼容模式.D 用于标识默认操作数的大小数据段的描述符格式如下:struct DataSegDesc {0 - 15: unsigned short limitLow; // 无效16-39: unsigned int baseLow : 24; // 无效40: unsigned int A : 1; // 无效41: unsigned int W : 1;42: unsigned int E : 1; // 无效43: unsigned int C/D: 1; // 固定为 044: unsigned int S : 1; // 固定为 145-46: unsigned int DPL : 2;47: unsigned int P : 1;48-51: unsigned int limitHigh : 4; // 无效52: unsigned int AVL : 1; // 无效53: unsigned int L : 1; // 无效54: unsigned int D : 1; // 无效55: unsigned int G : 1; // 无效56-63: unsigned char baseHigh; // 无效};其中, 只有 P 和 DPL 标志有效. W 标志只有作为堆栈段时要求必须为 1.由于段的基址被强制为 0, 所以虚拟地址和线性地址是等价的, 这个地址进行分页转换后成为物理地址.2. 分页Long Mode 下, 分页是必须的. 而且只有一种模式, 使用 4 层映射, 在 PAE 的上面又增加了一层. 页面的大小可以是 4K, 2M, 1G. 线性地址长度为 64 位, 目前使用的最高地址为 48 位. 对 4KB 的页面, 线性地址结构如下:struct LineAddress {0-11: unsigned int offset : 12; // 偏移12-20: unsigned int pte_index : 9;21-29: unsigned int pde_index : 9;30-38: unsigned int pdpte_index : 9;39-47: unsigned int pml4te_index : 9;48-63: unsigned int sign : 16; // 符号扩展位};其中的 48-63 位是符号扩展位, 要么全 0, 要么全 1, 必须与第 47 位相同. 这种地址被称为规范化地址(canonical address), 是为了方便以后将 48 位的地址扩展到更高位数时无需进行修改. 4 个 9 位的 index 分别是 4 种表结构的下标, 这些表结构的元素都是 8 字节 64 位的, 由于索引为 9 位, 所以这些表结构的大小都是 4KB. 第一个索引 pml4te_index 用于索引 PML4T(Page Map Level-4 Table, 表元素称为 PML4E), PML4T 的基址由 CR3 寄存器提供. CR3 被扩展为 64 位, 在不支持 PCIDE 功能时, CR3 的结构为:struct NormalCR3 {0- 2: unsigned int no_use1 : 3;3: unsigned int PWT : 1; // Page-level Write-Through4: unsigned int PCD : 1; // Page-level Cache Disable5-11: unsigned int no_use2: 7;12-47: unsigned int pml4t_base : 36;48-63: unsigned int receved : 16; // 保留为 0};PML4T 的基地址低 12 设置为 0, 按 4 KB 对齐. 高位从 CR3 的 12 位开始. 随着物理地址长度不同, 使用的位数也不同, 没有使用的位数则保留为 0.启用 PCID (CR4.PCIDE 1, PCID Process Context ID, 仅 Intel64 支持, AMD64 不支持) 后, CR3 的低 12 位表示 PCID 值, 第 63 位控制 CR3 切换时缓存的处理. 详情从略.根据 CR3 和 pml4t_index 可以寻到 PML4E 结构, 该结构描述如下:struct PML4E {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int no_use1 : 1;7: unsigned int receved : 1; // PS 位 必须为 08-11: unsigned int no_use2 : 4;12-47: unsigned int pdpt_base : 36;48-62: unsigned int receved : 15; // 保留为 0, 随物理地址大小扩展63: unsigned int XD : 1; // Execution Disable};其中的 pdpt_base 和 pml4t_base 一样, 第 12 位为 0, 高位可向保留位扩展, 以后的结构也都类似. XD 位和 PAE 模式中的 XD 位含义相同. 通过 PML4E 中的 pdpt_base 以及线性地址中的 pdpte_index 可以寻址到 PDPTE 结构, PDPTE 结构将控制 1G 页面的转换, 所以第 7 位 PS 位有效, 当 PS 1 时直接通过 PDPTE 结构转换 1G 的页面. 此时 PDPTE 结构如下:struct PDPTE_1G {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int D : 1;7: unsigned int PS : 1; // PS 位, 为 18: unsigned int G : 1;9-11: unsigned int no_use1 : 3;12: unsigned int PAT : 1;13-29: unsigned int receved : 17; // 保留, 必须为 030-47: unsigned int page_base : 18;48-62: unsigned int receved : 15;63: unsigned int XD : 1; // Execution Disable};其中的 page_base 的低 30 位为 0, 按 1GB 对齐, 高位可向保留位扩展. 线性地址中的 pde_index 和 pte_index 也用于表示偏移, 一个是 30 位的偏移. 由基址 偏移得到物理地址.当 PS 0 是, 页面是 4K 或 2M 的页面, PDPTE 需要提供 PDT 的基址, 此时的 PDPTE 结构如下:struct PDPTE {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int no_use1 : 1;7: unsigned int PS : 1; // PS 位, 为 08-11: unsigned int no_use2 : 4;12-47: unsigned int pdt_base : 36;48-62: unsigned int receved : 15; // 保留为 0, 随物理地址大小扩展63: unsigned int XD : 1; // Execution Disable};由其中的 pdt_base 和线性地址中的 pde_index 可寻找到 PDE 结构, PDE 中的 PS 位决定是 4KB 页面还是 2MB 页面, 当 PS 1 时页面为 2M, 此时 PDE 结构如下:struct PDE_2M {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int D : 1;7: unsigned int PS : 1; // PS 位, 为 18: unsigned int G : 1;9-11: unsigned int no_use1 : 3;12: unsigned int PAT : 1;13-20: unsigned int receved : 8; // 保留, 必须为 021-47: unsigned int page_base : 27;48-62: unsigned int receved : 15;63: unsigned int XD : 1; // Execution Disable};page_base 的低 21 位为 0, 按 2M 对齐, 线性地址 pte_index 用于表示偏移, 一共 21 位偏移, 由基址 偏移得到物理地址.PDE.PS 0 时, 页面为 4K, 继续寻找 PTE 结构, 此时的 PDE 为:struct PDE {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int no_use1 : 1;7: unsigned int PS : 1; // PS 位, 为 08-11: unsigned int no_use2 : 4;12-47: unsigned int pt_base : 36;48-62: unsigned int receved : 15; // 保留为 0, 随物理地址大小扩展63: unsigned int XD : 1; // Execution Disable};由 pt_base pte_index 最终得到 PTE 结构, 此时的 PTE 结构与 PAE 模式下是完全一致的:struct PTE {0: unsigned int P : 1;1: unsigned int R/W : 1;2: unsigned int U/S : 1;3: unsigned int PWT : 1;4: unsigned int PCD : 1;5: unsigned int A : 1;6: unsigned int D : 1;7: unsigned int PAT : 1; // PS 位变为 PAT 标志8: unsigned int G : 1;9-11: unsigned int no_use1 : 3;12-47: unsigned int page_base : 36;48-62: unsigned int receved : 15;63: unsigned int XD : 1; // Execution Disable};最终由 PTE 的 page_base 加上线性地址的 offset 得到物理地址, 漫长的寻址过程终于画上了句号.以下是网上搜集的描述长模式下寻址相关的图表:1. 线性地址到物理地址转换, 灰色路线是 2M 页面, 深灰色路线是 1G 页面, 黑色路线是 4K 页面的转换.