我正在尽我所能地理解这个OSDEV教程的内容。 我已经按照建议阅读了 AMD64 程序员手册(第 2 卷(第 4 章和第 5 章,但我不明白当他经历这个循环时会发生什么:
mov ebx, 0x00000003 ; Set the B-register to 0x00000003.
mov ecx, 512 ; Set the C-register to 512.
.SetEntry:
mov DWORD [edi], ebx ; Set the uint32_t at the destination index to the B-register.
add ebx, 0x1000 ; Add 0x1000 to the B-register.
add edi, 8 ; Add eight to the destination index.
loop .SetEntry ; Set the next entry.
我明白为什么他将 ebx 设置为 3,但除此之外,我看不出他对 ID 映射 2 MB 做了什么。
mov ebx, 0x00000003 ; Set the B-register to 0x00000003.
该代码使用 ebx 保存要写入下一页表条目的值。它将其初始化为3
以设置当前位和可写位(位 0 和 1(。从这里开始,它会在每次循环迭代时向其添加0x1000
,这不会影响这两个位。物理地址字段为零,因此这将使第一个条目映射到物理地址为零。
mov ecx, 512 ; Set the C-register to 512.
循环运行 512 次迭代,每个页表条目一次迭代。每个条目为 64 位(8 字节(。长模式下的一个页表可以容纳 512 个条目。512是4096/8。
.SetEntry:
mov DWORD [edi], ebx ; Set the uint32_t at the destination index to the B-register.
编写一页表条目。
add ebx, 0x1000 ; Add 0x1000 to the B-register.
将要写入下一页表条目的物理地址提前 4KB。每个页表条目映射 4KB。
add edi, 8 ; Add eight to the destination index.
将下一个页表条目写入页表的下一个条目中。每个页表条目为 8 个字节。
loop .SetEntry ; Set the next entry.
循环指令表示ecx = ecx - 1
jnz .SetEntry
.如果ecx
在将ecx
减少 1 后不为零,它将运行循环的另一个迭代。由于ecx
在循环之前被初始化为 512,这使得上述指令重复 512 次。
后续条目的物理地址高 4KB,并且每个条目映射 4KB,并且有 512 个,因此此代码使用标识映射前 2MB 物理内存的条目填充虚拟地址 0(含(到 2MB(独占(的页表条目。"身份"映射意味着映射它,使物理地址等于线性地址。长模式下的每个页表映射 2MB 的地址空间。由于此代码填充一个页表,因此它映射 2MB。
请注意,仅此代码不足以设置分页。此代码仅填充页表条目。此代码适用于 32 位 PAE 分页或长模式分页。
在 PAE 分页中,您还需要设置另外两个页面。对于长模式,您需要设置其他三个页面。PAE 分页使用 3 级转换,其中顶层映射 1GB 区域,中级映射 2MB 区域,页表级别映射 4KB 区域。
长模式分页使用 4 级(或者在最新处理器上,可以是 5 级(分页。在长模式下,顶层映射 512GB 区域,第二级映射 1GB 区域,第三级映射 2MB 区域,最外层映射 4KB 区域。
设置标识映射的代码除了问题中的代码中显示的设置外,还需要设置上述页面。