linux0.11中jmpi 0,8解析

本文详细阐述了在执行JMPI0,8指令时,如何利用段选择子和GDT表来定位内存地址,以及CR0寄存器在保护模式和分页机制中的角色。特别关注了GDT表的结构和内存段的配置,解释了为什么在计算物理地址时需要加上1。
摘要由CSDN通过智能技术生成

        系统在执行该行代码时已经为保护模式, jmpi 0,8会将段选择子(selector)载入cs段寄存器,并计算出逻辑地址。

段选择子的结构如下:

段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。

  • index(描述符索引)部分表示对应的段描述符在描述符表(GDT或者LDT)中的位置。然后GDTR或者LDTR中存储的描述符表基址 + index * 段描述符长度 就能得到对应描述符的地址
  • TI表示描述符表的类型,0=GDT,1=LDT
  • RPL--请求等级,有0,1,2,3四个取值,权限从大到小

在jmpi 0,8中,段选择子的值为8。按照二进制表示即为1000,那么

TI = 0          --GDT表
RPL = 0         --内核级访问权限
INDEX = 1       --GDT表第二个元素,从0开始

而段寄存器的格式如下:

Struct SegMent{
WORD	Selector段选择子;//16位selector
WORD	Attribute;//16位的Attribute
DWORD	Base;//32位的Base
DWORD	Limit	//32位的Limit
};

 那么上述的selector会被加载到段寄存器cs的selector部分,而段寄存器的不可见部分相当于缓存,它会将查询到的段的信息(段基值,段限长,可读可写等属性)缓存起来,当下次仍然用同样的段选择子去查询时就不用再查表,就直接用缓存的部分,相当于提高了执行效率,当然这与该文主题没有半毛钱关系,仅仅记录。

接下来就要去GDT表中查找段的信息,那GDT表到底长什么样子?以下是GDT表中元素的排列情况,可以看到内核代码段和数据段描述符分别为GDT表的第二(index=1)和第三(index=2)个元素。

GDT表中每个元素定义如下:

                                                                  图1

 G表示段界限粒度,为0时表示粒度为1字节,为1时表示粒度为4KB,一般置为1

 S表示是否为系统段,为1时表示系统段,为0时表示非系统段

可以看出每个段描述如占用8字节,即4个字

有了以上定义,只要知道其中的数据排列就能得出每个段的段基值和段界限,在源码中找到如下定义:

;// 全局描述符表开始处。描述符表由多个8 字节长的描述符项组成。
;// 这里给出了3 个描述符项。第1 项无用,但须存在。第2 项是系统代码段
;// 描述符(208-211 行),第3 项是系统数据段描述符(213-216 行)。每个描述符的具体
;// 含义参见列表后说明。
gdt:
	dw	0,0,0,0		;// 第1 个描述符,不用。
;// 这里在gdt 表中的偏移量为08,当加载代码段寄存器(段选择符)时,使用的是这个偏移值。
	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9A00h		;// code read/exec
	dw	00C0h		;// granularity=4096, 386
;// 这里在gdt 表中的偏移量是10,当加载数据段寄存器(如ds 等)时,使用的是这个偏移值。
	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9200h		;// data read/write
	dw	00C0h		;// granularity=4096, 386

那么jmpi 0,8中的index=1所指向的段描述符的内容如下:

	dw	07FFh		;// 8Mb - limit=2047 (2048*4096=8Mb)
	dw	0000h		;// base address=0
	dw	9A00h		;// code read/exec
	dw	00C0h		;// granularity=4096, 386

 按照图1中进行排列,注意按照小端格式排列:

经过组合

                     段基值为  0x00000000 = 0

                     段限长为 0x007FF = 2047, 即2048 * 4KB = 8M

此处为什么要+1,应该是一种约定。另外G=1,就表示段界限单位为4KB.  另外也可以得出段界限的最大空间为

(0xFFFFF + 1) * 4KB = 4GB

那么最后可以得出jmpi 0,8所要跳转到的物理地址为

                 base(0) + ip(0) = 0

此地址处就是操作系统核心的head.s文件存放在内存中的地址。此处的地址需要经过MMU转换吗?系统在现在的执行阶段,其实还没有开启分页机制,那么该0其实就是真实的物理地址。这些都是由CR0寄存器决定的, 可以把它认为是操作系统的动态配置。CR0寄存器格式如下:

 PE(Protection Enable)保护使能是CR0寄存器的第0位(bit 0)。当设置了PE标志时,启用保护模式;当清除PE标志时,启用实地址模式。该标志位并不直接启用分页机制,它仅启用段级别的保护。要启用分页,必须同时设置PE和PG标志。

Paging(分页)标志位是CR0寄存器的第31位。当该位被设置时(为1时),启用分页机制;当该位被清除时(为0时),禁用分页机制。当分页被禁用时,所有线性地址都被视为物理地址。也就是说没有分页机制,段机制通过段基址加偏移后就是真实物理地址,如果PE标志(寄存器CR0的第0位)未设置,PG标志则没有影响;在PE标志被清除时设置PG标志会导致通用保护异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值