再谈分段

我们已经知道CPU的分段机制的作用在于将程序逻辑地址映射为线性地址,CPU在启动了保护模式之后,其段寄存器不再作为地址内容的一部分,而是作为一种称为选择子的东西,它作为在全局描述符表或者局部描述符表中寻找目标地址的索引,所以对于程序中每一个地址的寻址就需要指定两个事物,第一个就是选择子,第二个就是描述符表。选择子就是段寄存器,而描述符表就是一个全局数组变量。这个描述符表其实应该是二维的数组,第一维度表示描述符的索引号,第二维度表示描述符的内容。对于描述符的内容,它占据的内存空间为8字节,可以先想象一下程序在保护模式下的内存寻址,肯定最关键的要指定内存的基地址,所以第二维度的8字节内容里面肯定包含了基地址,除了基地址外,还有段的长度以及段的属性,设置这两个字段是为了限制程序的安全范围,所以保护模式这个说法也就是指的就是这个。另外为了能让CPU能够找到这个全局描述符数组,我们还需要将这个数组的地址加载到gdtr寄存器中。

上面提到了全局描述符和局部描述符,那么他们之间有什么关系和区别呢。首先我们已经知道全局描述符是一个以8字节为一个单元的二维数组,每一个单元里面指定了段基址,段长度以及段属性,另外全局描述符在保护模式下有且仅有一个。而对于局部描述符是不是也要定义一个二位数组呢?是的,系统中的每一个用户进程就应该对应相应的一个局部描述符,所以局部描述符在一个系统中就会存在多个,但是这里就有一个问题了:唯一的一个全局描述符数组的地址可以指定在gdtr寄存器中,但是局部描述符有多个并且数量未知,是不是cpu也为每一个局部描述符数组事先准备好了地址呢?如果是这样,那CPU成本可就高了。是这样的,每个局部描述符数组的地址由全局描述符来指定,什么意思呢,局部描述符不再像全局描述符那样单独指定一个寄存器来存储其地址,而是借助全局描述符表的一个描述符来寻址,这个全局描述符中就存储了局部描述符的地址。另外在寻址具体的局部描述符时,需要事先在ldtr寄存器中将对应进程的局部描述符所对应的全局描述符选择子加载进去,也就是说ldt寄存器里面保存的是一个进程局部描述符表地址的选择子。当然寻址时为了区分全局和局部描述符,选择子的属性是不同的(T1位)。对于一个用户进程的寻址过程再总结下,首先CPU发现段选择子是局部描述符选择子,然后CPU会根据ldtr寄存器的内容在全局描述符表中找到对应局部描述符表的基地址,最后根据选择子索引到局部描述符对应的内存。

除了全局描述符和局部秒符之外,还有一个中断描述符。其实中断描述符跟全局描述符基本类似,全局描述寻址时需要在gdtr寄存器中指定描述符表的地址,中断描述符也是一样,使用时需要在idtr寄存器中指定描述符表地址。因为有了这个这个中断描述符的存在,所以CPU保护模式中的中断机制跟实模式完全不同了,比如说int 13指令,在实模式下执行该指令会跳到BIOS事先准备好的内存地址处执行,并且完成预设好的功能;而在保护模式下执行这条指令,CPU首先根据idtr寄存器指定的中断描述符表的地址找到以13为索引的8字节中断描述符,然后根据该描述符的内容找到对应的中断入口地址,所以这个8字节的中断描述符中必然包含中断函数的所在的段以及偏移地址,这个段一般指定为内核段,当然保护模式下肯定为选择子。当然除了段和偏移外,还包含有一些属性字段,具体可以查看相关资料。总结一下保护模式下中断的寻址,首先要初始化一个中断描述符表,其实就是一个二维的数组,注意中断向量号(int后面跟的数字)就是该数组的索引,然后这是产生一个中断(可能是CPU异常或者使用int xx指令),CPU根据根据中断向量号在idtr寄存器指定的中断描述符表中获取中断函数的入口地址(由段和偏移指定),最后执行中断处理程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值