linux 内核源代码情景分析——Intel X86 CPU 系列的寻址方式
当我们说一个CPU是“16位”或“32”位时,指的是处理器中“算数逻辑单元”(ALU)的宽度。数据总线通常与ALU具有相同的宽度。当Intel决定在16位CPU 8086中采用1M字节的内存空间,地址总线的宽度也就确定了,那就是20位。问题就来了:既然是ALU是16位,也就是说直接加以运算的指针长度是16位,即这个指针所能代表的地址最多有216,不能达到20位地址总线所能寻址的最大空间,于是Intel在8086 CPU中设置了4个“段寄存器”:CS、DS、SS和ES,分别用于可执行代码、数据、堆栈和其他。每个段寄存器都是16位的,对应于地址总线中的高16位。每条“访内”指令中的“内部地址”都是16位的,但是在送上地址总线之前都在CPU内部自动的与某个段寄存器的内容相加,形成一个20的实际地址。这样,就实现了从16位内部地址到20位实际地址的转换。转换公式:实际地址 = 段寄存器 + (内部地址<<4)。
由于8086这种到内存寻址方式缺乏对内存空间的保护,所以为了区别于后来的“保护模式”,就称为“实地址模式”。针对8086这种缺陷,Intel从80286开始实现“保护模式”,不久后80386 CPU也开发成功了,从80386以后,虽然在速度和功能上不断的提改进,但并无重大的质的改变,遂统称为i386结构,下面我们将以80386为背景,介绍i386的保护模式。
1、虚拟地址、逻辑地址、线性地址、物理地址的区别

由图可以看出它们之间的区别
2、分段机制

分段步骤:
1)先检查段选择符TI,确定段描述符保存在GDTR还是LDTR中
2)从段选择符高13位(见下图的段选择符格式)* 8 + GDTR中的内容得到段基地址。也可以这样想,GDTR存放的是段描述符表这个数组的首地址,而段选择符的高13位*8是其下标,因为段描述符是8字节长,所以在段描述表里是以8字节为一个单位
3)然后将2)得到的值与偏移量相加就得到了线性地址
3、段选择符格式

GDT的第一项是”空选择符“(即索引值为0,TI标志为0),当把它加载到一个段寄存器(除了CS和SS之外)中时,处理器不会产生异常,但是当使用含有空选择符的段寄存器访问内存时就会产生异常。段选择符的值通常由链接编辑器或链接加载程序进行设置或修改,而非应用程序.
为了减少地址转换时间和复杂性,处理器提供了6个段寄存器,为了访问某个段的程序,必须把段选择符加载到一个段寄存器中,为了避免每次访问内存时都去读、解码一个段描述符和引用段描述符表,每个段寄存器都有一个“可见”部分和“隐藏”部分(影子寄存器),当一个段选择符被加载到一个段寄存器可见部分中时,处理器也同时把段选择符指向的段描述符中的段地址、段限长和访问控制信息加载到段寄存器的隐藏部分中。缓冲在段寄存器(可见和隐藏部分)中的信息时的处理器可以在进行地址转换时不再需要花费时间从段描述符中读取基地址和段限长。操作系统必须保证对描述符表的改动反映到影子寄存器中,最简单的方法是在对描述符表中描述符作过任何改动之后就立刻重新加载6个段寄存器
4、段描述符格式

B31——B24、B23——B16、B15——B0组合成段基地址Base,Base为32位
L19——L16、L15——L0组合成段限长Limit,Limit为20位
G颗粒度,G=0,Limit单位是字节,G=1,Limit单位是4KB
D 如果段偏移量是32位置1,若是16位,清0
AVL 系统软件可用位,忽略
P为0表示不在内存中,linux总是为1
DPL 表示为访问这个段而要求的CPU最小的优先级
S系统标志:0表示是一个系统段,否则是普通的代码段或数据段
type 指定段的类型、说明段的访问种类以及段的扩展方向
linux 内核源代码情景分析——Intel X86 CPU 系列的寻址方式的更多相关文章
- Linux内核源代码情景分析系列
http://blog.sina.com.cn/s/blog_6b94d5680101vfqv.html Linux内核源代码情景分析---第五章 文件系统 5.1 概述 构成一个操作系统最重要的就 ...
- Intel X86 CPU 系列的寻址方式
Intel X86 CPU 系列的寻址方式 数据总线和地址总线要尽量相同,这个是一个地址就是一个指针.
- linux 内核源代码情景分析——地址映射的全过程
linux 内核采用页式存储管理.虚拟地址空间划分成固定大小的"页面",由MMU在运行时将虚拟地址映射成某个物理内存页面中的地址.页式内存管理比段式内存管理有很多好处,但是由于In ...
- Linux内核源代码情景分析-fork()
父进程fork子进程: child = fork() fork经过系统调用.来到了sys_fork.具体过程请參考Linux内核源码情景分析-系统调用. asmlinkage int sys_fork ...
- linux 内核源代码情景分析——linux 内存管理的基本框架
386 CPU中的页式存管的基本思路是:通过页面目录和页面表分两个层次实现从线性地址到物理地址的映射.这种映射模式在大多数情况下可以节省页面表所占用的空间.因为大多数进程不会用到整个虚存空间,在虚存空 ...
- linux 内核源代码情景分析——linux 内核源代码中的C语言代码
linux 内核的主体是以GNU的C语言编写的,GNU为此提供了编译工具gcc.GNU对C语言本身作了不少扩充. 1) gcc 从 C++ 语言中吸收了"inline"和" ...
- linux 内核源代码情景分析——用户堆栈的扩展
上一节中,我们浏览了一次因越界访问而造成映射失败从而引起进程流产的过程,不过有时候,越界访问时正常的.现在我们就来看看当用户堆栈过小,但是因越界访问而"因祸得福"得以伸展的情景. ...
- linux 内核源代码情景分析——linux 内核源码中的汇编语言代码
1. 用汇编语言编写部分核心代码的原因: ① 操作系统内核中的底层程序直接与硬件打交道,需要用到一些专用的指令,而这些指令在C语言中并无对应的语言成分: ② CPU中的一些特殊指令也没有对应的C语言成 ...
- Linux内核源代码情景分析-中断半
一.中断初始化 1.中断向量表IDT初始化 void __init init_IRQ(void) { int i; #ifndef CONFIG_X86_VISWS_APIC init_ISA_irq ...
随机推荐
- 在PHP中使用SPL库中的对象方法进行XML与数组的转换
虽说现在很多的服务提供商都会提供 JSON 接口供我们使用,但是,还是有不少的服务依然必须使用 XML 作为接口格式,这就需要我们来对 XML 格式的数据进行解析转换.而 PHP 中并没有像 json ...
- PHP的Mhash扩展函数的学习
这次我们要学习的又是一个 Hash 加密扩展.不过这个扩展 Mhash 已经集成在了 Hash 扩展中.同时也需要注意的是,这个扩展已经不推荐使用了,我们应该直接使用 Hash 扩展中的函数来进行 H ...
- Influxdb数据库 - 基本操作
InfluxDB数据库的简介 InfluxDB是一个用于存储和分析时间序列数据的开源数据库,是一个基于 golang 编写,用于记录 metrics.events,进行数据分析. 主要特性有: 内置H ...
- 一朵云、一张网、一体化 ——GRTN 打造最佳流媒体场景实践
阿里巴巴 GRTN 是面向流媒体云原生设计的,方便客户构建自己的流媒体云原生应用,让流媒体服务无处不在. 在近期召开的分布式云主题报告会上,阿里云资深技术专家卢日发表了题为<GRTN 打造阿里云 ...
- Keras函数——mode.fit_generator()
1 model.fit_generator(self,generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validati ...
- join方法个人理解
首先抛出对join的疑问 如果我有一个a线程,一个b线程 那此时 a.start(); b.start(); a.join(); b.join(); 是否意思是a线程先执行完,然后再执行b线程; 如果 ...
- 2017年第二届广东省强网杯线上赛WEB:Musee de X writeup(模板注入漏洞)
目录 解题思路 总结 解题思路 拿到手上,有四个页面 首先按照题目要求执行,尝试注册一个名为admin的账户 这种情况,路径都给出来了,很可能就是目录遍历或者文件上传了 回到初始界面,点击链接here ...
- 1-SQL Server2019安装
sql server2019安装 首先去官网下载(下载express版本): 打开安装程序 选择自定义 更改一下安装目录,点击安装 等待安装 等安装完成后,出现如下页面 选择SQL Server独立安 ...
- UDP用户数据报
UDP 用户数据报协议UDP只在IP的数据报服务之上增加了很少的一个功能,就是复用,分用,差错检测功能.UDP的主要特点是: UDP是无连接的,即在发送数据报之前不需要建立连接(当然发送数据结束的时候 ...
- 1.1 jvm核心类加载器--jdk源码剖析
目录 前提: 运行环境 1. 类加载的过程 1.1 类加载器初始化的过程 1.2 类加载的过程 1.3 类的懒加载 2. jvm核心类加载器 3. 双亲委派机制 4. 自定义类加载器 5. tomca ...