您的位置:首页 > 运维架构 > Linux

CPU的寻址方式(Linux内核情景分析)

2016-05-17 14:10 274 查看
Intel在8086 CPU中设置了四个“段寄存器”:CS、DS、SS和ES,分别用于可执行代码即指令、数据、堆栈和其他。

每个段寄存器都是16位的,对应于地址总线中的高16位。

每条“访内”指令中的“内部地址”都是16位的,但是在送上地址总线之前都在CPU内部自动地与某个段寄存器中的内容相加,形成一个20位的实际地址。(映射)

段寄存器中的内容对应于20位地址总线中的高16位;

相加时拿内部地址中的高12位与段寄存器中的16位相加;

对于每一个由段寄存器的内容确定的“基地址”,一个进程总是能够访问从此开始的64K字节的连续地址空间,而无法加以限制。(没有地址空间的保护机制)

通过改变段寄存器的内容,一个进程可以随意访问内存中的任何一个单元。

8086的这种内存寻址方式缺乏对内存空间的保护,就称为“实地址模式”。

i386系列的保护模式

同一种系统结构中的改进与加强。

支持实地址模式,又要能支持保护模式。

Intel设计人员的基本思路是:在保护模式下改变段寄存器的功能,使其从一个单纯的基地址变成指向一个数据结构的指针。

(1)根据指令的性质来确定应该使用哪个段寄存器;

(2)根据段寄存器的内容,找到相应的“地址段描述结构”;

(3)从地址段描述结构中的到基地址;

(4)将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,看看是否越界;

(5)根据指令的性质和段描述符中的访问权限来确定是否越权;

(6)将指令中发出的地址作为位移,与基地址相加得到实际的“物理地址”。

段描述结构在实际使用时将其装载入CPU中的一组“影子”结构。

80386CPU中增设了两个寄存器:全局性的段描述表寄存器GDTR(global descriptor table register)和局部性的LDTR(local descriptor table register)。

用来指向存储在内存中的段描述表。

访问这两个寄存器的专用指令设计为“特权指令”。

段寄存器的高13位用作访问段描述表中具体描述结构的下标(index);

TI = 0时使用GDTR, = 1时使用LDTR;

RPL == 00最高级, 11 = 最低级。

GDTR或LDTR中的段描述表指针和段寄存器中给出的下标结合在一起,才决定了具体的段描述表项在内存中的什么地方。

每个段描述表项的大小是8个字节,含有段的基地址和段的大小,再加上其它一些信息。

每当一个段寄存器的内容改变时(通过MOV、POP等指令或发生中断等事件),CPU就把由这段寄存器的新内容所决定的段描述项装入CPU内部的一个“影子”描述项。

CPU中有几个段寄存器就有几个影子描述项。

在80386的段式内存管理基础上,如果把每个段寄存器都指向同一个描述项,而在该描述项中将基地址设为0,并将段长度设成最大,这样便形成了一个从0开始覆盖整个32位地址空间的一个整段。

由于基地址为0,此时的物理地址与逻辑地址相同,CPU放到地址总线上的地址就是指令中给出的地址。

用来装入和存储GDTR和LDTR的指令LGDT/LLDT和SGDT/SLDT等都是特权指令。

用户程序不但不能改变GDTR和LDTR的内容,还无法确知其段描述表在内存中的位置,也无法访问其空间,从而无法通过修改段描述项来打破系统的保护机制。

80386如何分隔系统状态和用户状态

80386划分成四个特权级别,0级为最高,3级为最低,每一条指令都有其适用级别。

LGDT特权指令中有在0级下才能使用,一般的输入/输出指令(IN,OUT)则规定为0级或1级。用户的应用程序都是3级。

一般程序的当前运行级别由其代码段的局部描述项中的dpl字段(descriptor privilege level)决定。

每个描述项中的dpl字段都是在0级状态下由内核设定。

全局段描述的dpl字段表示所需的级别。

i386 CPU中还有中断向量表指针寄存器IDTR、与进程有关的寄存器TR以及描述任务状态的“任务状态段”TSS等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: