linux kernel learn1
来源:互联网 发布:淘宝买家信誉在哪里看 编辑:程序博客网 时间:2024/05/22 17:01
Intel X86 CPU 系列的寻址方式
我们说一个CPU是16 位或者32位时,指的是处理器中“逻辑算术单元”(ALU)的宽度。系统总线中的数据线部分,称为“数据总线”,通常与ALU 具有相同的宽度(但有例外)。最自然的地址总线宽度是与数据总线一致。因为从程序设计角度来说,一个地址,也就是一个指针,最好与一个整数的长度一致。
在16位CPU 8086中采用1M字节的内存地址空间,地址总线的宽度也就相应的确定了,即20位。如何将地址总线的20位映射成可以直接被CPU加以运算的16位地址空间,就成为一个问题:现在看来,当时设计人员采用了一种不失巧妙的方法, 即分段的方法。
Intel在8086CPU中设置了四个“段寄存器”:CS、DS、SS和ES,分别用于可执行代码即指令、数据、堆栈和其他。每个段寄存器都是16位的,对应于地址总线中的高16位。每条“访内”中的“内部地址”都是16位的,但是在送上地址总线之前都在CPU内部自动地与某个段寄存器中的内容相加,形成一个20位的实际地址。这样,就实现了从16位内部地址到20位实际地址的转换,或者“映射”。注意:段寄存器中的内容对应于20位地址总线中的高16位,所以在相加时实际上是拿内部地址中的高12位与段寄存器中的16位相加,而内部地址中的低4位保留不变。这个方法与操作系统理论中的“段式内存管理”相似,但并不完全一样,主要是没有地址空间的保护机制。由于8086的这种内存寻址方式缺乏对内存空间的保护,所以为了区别后来出现的“保护模式”,就称为“实地址模式”。
Intel选择了在段寄存器的基础之上构筑保护模式的构思,并且保留了段寄存器为16位(这样才可以利用原有的四个段寄存器),但是却又增添了两个段寄存器FS和GS。为了实现保护模式,光是用段寄存器来确定一个基地址是不够的,至少还得要有一个地址段的长度,并且还需要一些其他信息,如访问权限之类。所以这里需要的是一个数据结构,使其从一个单纯的基地址(变相的基地址)变成指向这样一个数据结构的指针。这样,当一条访问内存指令发出一个内存地址时,CPU就可以这样来归纳出实际上应该放上数据总线的地址:
1.根据指令的性质来确定该使用哪一个段寄存器,例如转移指令中的地址在代码段,而取数指令中的地址在数据段。这一点与实地址模式相同。
2.根据段寄存器的内容,找到相应的“段地址描述结构”
3.从段地址描述结构中得到基地址。
4.将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,看看是否越界。
5.根据指令性质和段描述结构中的访问权限来确定是否越权。
6.将指令中发出的地址作为位移,与基地址相加而得出实际的“物理地址”。
80386 的段式内存管理机制:
首先,在80386CPU 中增设两个寄存器:一个是全局性的段描述表寄存器GDTR(global descriptor table register),另一个是局部性的段描述表寄存器LDTR(local descriptor table register)。分别可以用来指向存储在内存中的一个段描述结构数组,或者称为段描述表。访问这两个寄存器的指令被设计成“特权指令”。
在此基础上,段寄存器的高13位(低3位另做他用)用作访问段描述表中具体描述结构的index。如下图所示:
GDTR或者LDTR中的段描述表指针和段寄存器中给出的下标结合在一起,才决定了具体的段描述表项在内存中的什么地方,换句话说,将段寄存器内容的低3位屏蔽掉以后与GDTR或LDTR中的基地址相加得到描述表项的起始地址。每个段描述表项的大小是8个字节,每个描述表项含有段的基地址和段的大小,再加上一些其他信息,其结构如图所示:
结构中的B31~B24和B23~B16分别是基地址的bit16~bit23和bit24~bit31。而L19~L16和L15~L0则为段长度的bit0~bit15和bit16~bit19。其中DPL是两个位的为段,而type是一个4位的位段。
- linux kernel learn1
- WAP Learn1
- c++ learn1
- Java4Andriod 从零学起 ---learn1
- c#learn1装箱&拆箱
- linux kernel
- Linux Kernel
- Linux kernel
- Linux kernel
- linux kernel
- linux kernel
- Linux Kernel
- Linux Kernel
- "android linux kernel" VS "standard linux kernel"
- "android linux kernel" VS "standard linux kernel"
- qemu linux kernel & vmware linux kernel
- Linux kernel management style
- Linux Kernel Makefiles(转)
- Java图片上传压缩处理
- Android Support Library介绍
- 函数式程序的模块化和对象的模块化
- 关于开发时遇到的乱码问题
- TCP/IP五层与OSI七层
- linux kernel learn1
- Android Fragment 解析(上)
- av_seek_frame中flags值的意义
- 欢迎使用CSDN-markdown编辑器
- synchronized的理解
- SAP GUI740 PATCH8 下载
- 浅谈javascript的Array.prototype.slice.call
- enum转换
- [Android] LayoutInflater 工作流程