Linux0.11内核--启动代码分析setup.s 建立页目录和页表

head.s开始

pg_dir

....

....

....

....

.org 0x1000

pg0:

.org 0x2000

pg1:

.org 0x3000

pg2:

.org 0x4000

pg3:

.org 0x5000

后面是setup_paging代码

其中:

movl $pg0+7,pg_dir /* set present bit/user r/w */

movl $pg1+7,pg_dir+4 /* --------- " " --------- */

movl $pg2+7,pg_dir+8 /* --------- " " --------- */

movl $pg3+7,pg_dir+12 /* --------- " " --------- */

设置页目录表中的项

由于pg0的地址在0x1000位置,则$pg0+7表示的是0x00001007

第 1 个页表的属性标志 = 0x00001007 & 0x00000fff = 0x007,表示该页存在、用户可读写。(由于每个页大小为4K,用12 bit位表

示)

然后

movl $pg3+4092,%edi

movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */

std

1: stosl /* fill pages backwards - more efficient :-) */

subl $0x1000,%eax

jge 1b

填写4个也表的内容

由于每个页表有1024项*4个页表=4096项,4096*4K=16M,正好完全覆盖地址空间。

Linus是从后向前设置页表,最后一个页表的最后一项对应的地址为16M-4096,即0xFFF000,然后加上属性标志0x007,得0xFFF007

每写一项地址减0x1000,也就是减去4K,正好对应一个页。

这程序循环0xFFF+1次

最后:

设置页目录基址寄存器 cr3 的值,指向页目录表

设置启动使用分页处理(cr0 的 PG 标志,位 31)

使用ret指令,将main函数地址从栈中弹出至CS,跳转到main去执行。

你可能感兴趣的:(linux)