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的bz2压缩扩展工具
在日常的开发和电脑使用中,我们经常会接触到压缩和解压的一些工具,PHP 也为我们准备了很多相关的操作扩展包,都有直接可用的函数能够方便的操作一些压缩解压功能.今天,我们先学习一个比较简单但不太常用的压 ...
- Shell系列(13)- read
前言 作用是往脚本中传递参数,之前文章的位置参数变量也有此功能,但是只适用于脚本的作者,为什么?第三方用户不知道这个脚本要传递哪些参数,这些参数分别是什么.本篇随笔read就可以实现上述功能,别且该命 ...
- 接口管理工具swagger
swagger,一款致力于解决接口规范化.标准化.文档化的开源库,一款真正的开发神器. swagger三大部分 Editor https://swagger.io/tools/swagger-edit ...
- 浅谈语音质量保障:如何测试 RTC 中的音频质量?
日常音视频开会中我们或多或少会遭遇这些场景:"喂喂喂,可以听到我说话吗?我听你的声音断断续续的","咦,我怎么可以听到回声?","太吵啦,我听不清楚你 ...
- P7324-[WC2021]表达式求值【dp】
正题 题目链接:https://www.luogu.com.cn/problem/P7324 题目大意 给一个只包含\(m\)个值的表达式,\(<\)表前后取最小值,\(>\)表前后取最大 ...
- 什么?你还不明白自动化的POM设计模式?
POM简介.POM优势.如何设计POM POM简介 Page Object Model (POM) 直译为"页面对象模型",这种设计模式旨在为每个待测试的页面创建一个页面对象(cl ...
- requests之POST请求
上一节我们讲了GET请求,今天我们来讲讲POST请求. 学习一个新的模块,其实不用去百度什么的,直接用 help 函数就能查看相关注释和案例内容.如图所示,就是我们今天需要学习的内容. 1.用上面给的 ...
- CreateRemoteThread创建远程线程
要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程 该函数的原型如下: HANDLE CreateRemoteThread( HANDLE hP ...
- 在你面前有一个n阶的楼梯,你一步只能上1阶或2阶。 请问,当N=11时,你可以采用多少种不同的方式爬完这个楼梯();当N=9时呢?
在你面前有一个n阶的楼梯,你一步只能上1阶或2阶.请问,当N=11时,你可以采用多少种不同的方式爬完这个楼梯:当N=9时呢? 思路解析 ①台阶只有一级阶梯时,只有一种走法. ②当台阶有两级时,可以先走 ...
- 11.4.4 LVS-Fullnat
lvs-fullnat(双向转换) 通过请求报文的源地址为DIP,目标为RIP来实现转发:对于响应报文而言,修改源地址为VIP,目标地址为CIP来实现转发: CIP --> DIP VIP -- ...