Linux0.11 源码中的内存分页机制

      学习Linux的源码,《深入linux 内核架构》这本书看起来就让人害怕,然后就想着看看早期的linux版本的源码,从网上查看资料发现linux0.11 这个版本有很多人拿来当成教学版本,而且也有很多的参考书以这个版本作为基础来讲解,于是就从这个版本看起,本文主要是总结一下head.s这个汇编源码中的内存分页机制的建立。  

      linux 大神关于这个的代码很少,但是完整的建立了内存分页的页目录和页表。

/*
 * I put the kernel page tables right after the page directory,
 * using 4 of them to span 16 Mb of physical memory. People with
 * more than 16MB will have to expand this.
 */
.org 0x1000
pg0:

.org 0x2000
pg1:

.org 0x3000
pg2:

.org 0x4000
pg3:

.org 0x5000
/*

setup_paging:
	movl $1024*5,%ecx		/* 5 pages - pg_dir+4 page tables */
	xorl %eax,%eax
	xorl %edi,%edi			/* pg_dir is at 0x000 */
	cld;rep;stosl
	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		/*  --------- " " --------- */
	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
	xorl %eax,%eax		/* pg_dir is at 0x0000 */
	movl %eax,%cr3		/* cr3 - page directory start */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */

   现在我们就从一个初学者的角度来解读这些汇编代码然后看看最后的效果。

	movl $1024*5,%ecx		/* 5 pages - pg_dir+4 page tables */
	xorl %eax,%eax
	xorl %edi,%edi			/* pg_dir is at 0x000 */
	cld;rep;stosl

 这一段代码是将从地址为0 开的20K 数据全部置位0. movl $1024*5,%ecx 是将ecx 寄存器设置为 1024*5. 然后将eax 和edi 寄存器全部设置为0x00000000(32位)。

cld;rep;stosl

这三条指令组合在一起用于在内存中填充数据。

  • cld:这条指令设置方向标志(Direction Flag)为0,意味着接下来的字符串操作将从低地址向高地址进行。
  • rep:这是一个前缀,它告诉处理器接下来的字符串操作应该重复执行,直到 %ecx 寄存器的值减到0为止。
  • stosl:这是一个字符串操作指令,它将 %eax 寄存器中的值(在这里是0,因为我们之前清零了 %eax)存储到由 %edi 寄存器指向的内存地址,并递增 %edi 的值(一次递增4)。

然后再往页目录中写入内容,$pg0+7 是0x00001007,$pg1+7 是0x00002007,$pg2+7 是0x00003007,$pg3+7 是0x00004007

	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		/*  --------- " " --------- */

 把0x00001007 转换成二进制 000000000000000000001 000000000111可以看出对应的是页表第一项。

后面这一段代码用来填充页表项的内容

	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个页表项需要写入值,std 设置为1,表示要从高地址往低地址来写。第一个写入的位置是页表三的最后一项,写入的内容是0x00fff007,写完之后写下一个,地址是$pg3+4092 -4,写入的内容是0x00ffe007,一直到eax的值为0.

 线性地址的通过页目录和页表来获取物理地址的位置。

 13M 位置的0000 0000 1101 0000 0000 0000 0000 0000 

页目录项0x3,页表项0x100,页内偏移地址0x0。

0x100 * 4k =256* 4 K =1M,而页表3 的起始地址是12M 所以就可以定位到13M的地址上面。

最后来设置页目录寄存器cr3 的值和设置启动分页处理标志位

	xorl %eax,%eax		/* pg_dir is at 0x0000 */
	movl %eax,%cr3		/* cr3 - page directory start */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */

最后内存中的布局如下:

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值