我正在尽我所能地理解这个OSDEV tutorial到底是怎么回事。我已经按照建议阅读了AMD64程序员曼努尔(第二卷)第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 map 2MB做了什么。
发布于 2018-08-22 03:06:26
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减1后,如果ecx不为零,则会运行另一次循环迭代。由于在循环之前ecx已初始化为512,因此这会使上述指令重复512次。
由于第一个条目使用物理地址0,并且每个后续条目的物理地址比物理地址高4KB,并且每个条目映射4KB,并且有512个条目,因此此代码用标识映射物理内存的前2MB的条目填充虚拟地址0(包括)到2MB (不包括)的页表条目。“身份”映射意味着对其进行映射,以便物理地址等于线性地址。长模式下的每个页表映射2MB的地址空间。由于此代码填充了一个页表,因此它映射2MB。
请注意,仅有这段代码不足以设置分页。此代码仅填充页表条目。此代码适用于32位PAE分页或长模式分页。
在PAE分页中,您还需要设置另外两个页面。对于long模式,您需要设置其他三个页面。PAE分页采用3级转换,顶层映射1G区域,中层映射2MB区域,页表级别映射4KB区域。
长模式分页使用4级(或者在最新的处理器上,它可以是5级)分页。在长模式下,顶层映射512 1GB区域,第二层映射1 1GB区域,第三层映射2MB区域,最外层映射4KB区域。
除了您问题中的代码中所示的设置之外,设置身份映射的代码还需要设置上述页面。
https://stackoverflow.com/questions/45665451
复制相似问题