> For the complete documentation index, see [llms.txt](https://richardweiyang-2.gitbook.io/kernel-exploring/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://richardweiyang-2.gitbook.io/kernel-exploring/nei-cun-guan-li/00-evolution_of_kernel_pagetable/01-pagetable_before_decompressed.md).

# 未解压时的内核页表

这或许是x86平台启动过程中第一张页表了。

之前我们也学习了内核启动镜像bzImage由两部分组成setup.bin和vmlinux.bin。而这张第一章页表就在vmlinux.bin的head.S中。

如果对上述两个文件编译过程不熟悉的话可以参考下面的链接：

* [启动镜像bzImage的前世今生](/kernel-exploring/00_index/07_rules_for_bzimage.md)
* [真假vmlinux--vmlinux.bin揭开的秘密](/kernel-exploring/00_index/09_rule_for_vmlinux_bin.md)

## 先来看个代码

这第一张页表初始化的代码就在arch/x86/boot/compressed/head\_64.S中。

```
 /*
  * Build early 4G boot pagetable
  */
	/* Initialize Page tables to 0 */
	leal	pgtable(%ebx), %edi
	xorl	%eax, %eax
	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
	rep	stosl

	/* Build Level 4 */
	leal	pgtable + 0(%ebx), %edi
	leal	0x1007 (%edi), %eax
	movl	%eax, 0(%edi)

	/* Build Level 3 */
	leal	pgtable + 0x1000(%ebx), %edi
	leal	0x1007(%edi), %eax
	movl	$4, %ecx
1:	movl	%eax, 0x00(%edi)
	addl	$0x00001000, %eax
	addl	$8, %edi
	decl	%ecx
	jnz	1b

	/* Build Level 2 */
	leal	pgtable + 0x2000(%ebx), %edi
	movl	$0x00000183, %eax
	movl	$2048, %ecx
1:	movl	%eax, 0(%edi)
	addl	$0x00200000, %eax
	addl	$8, %edi
	decl	%ecx
	jnz	1b

	/* Enable the boot page tables */
	leal	pgtable(%ebx), %eax
	movl	%eax, %cr3
```

看到最后把地址保存到了cr3了么？Yep, you get it.

干这么看确实有点枯燥，不过简单来说就是分别填写了三层结构，构造出了一张覆盖4G大小的页表。

PS: 此时页表并没有启用，而是要等到后面CR0中的PG被置位后。

## 再来看一张图

看着图再去对照代码，我相信你就可以看懂了。

![这里写图片描述](/files/-LcGhm8iPj05W00K3IEO)

这样是不是清晰了很多。

代码我就不多说了，多看几遍自然就懂了。正所谓

> 代码虐我千百遍，我待代码如初恋

## 重要提醒

大家看这张表，有没有意识到什么特别的地方？对了，虚拟地址和物理地址是一样的。

那内核中的虚拟地址又是如何访问的呢？别着急，这一切才刚刚开始～
