一步步编写操作系统 11 实模式下程序分段的原因

cpu中本来是没有实模式这一称呼的,是因为有了保护模式后,为了将老的模式区别开来,所以称老的模式为实模式。这情况就像所有同学坐在同一个教室里,本来没有老同学这一概念,但某天老师领着一个陌生人进入教室并和大家宣布:“这是新转到我们班的韩梅梅,大家欢迎新同学”。得,无形之中,大伙儿就成了老同学。

实模式的“实”体现在:程序中用到的地址都是真实的物理地址,“段基址:段内偏移”产生的逻辑地址就是物理地址,也就是程序员看到的完全是真实的内存。

不过要说实模式,咱们还得从cpu的发展说起,任何事物发展到今天,都是有一段“合理”的过程,了解这一过程是怎么来的,有助于理解它今天的形态。

不知道各位同学当初学习汇编语言时有没有这样疑问:“老师都是拿8086型号的cpu举例,为什么不拿最新型号的呢?用那么古老的cpu讲解知识,是否已经落伍太久了,我们学习的知识到社会上能用吗?”我记得当初学习汇编时,那时的cpu都是奔腾2.8了。我带着这样的疑问请教了老师,老师回答我说:“8086是intel历史上第一个x86的cpu,也就是自那以后的cpu称为286、386、486、586…即使是现在的奔腾也是属于x86体系,道理是不变的,而且,用最简单的8086 cpu学习,这才更容易理解和看透cpu运行机制。”一番话彻底打消了我的疑虑,自那以后我才理解x86中的x原来是个变量^_^,它是指代intel所有86系列的产品。

在8086之前的cpu是什么样呢?为什么8086就可以称为cpu界的里程碑呢?原因是这样的,在它之前的cpu前辈们,对内存的访问比8086还要“实诚”,它们没有段的概念,程序中要访问内存,需要把地址写死,也就是所谓的“硬编码”,这其实很麻烦的,首先程序无法重定位,必须加载到内存中固定的位置,如果在此位置有其它程序在用,得,您先睡会,等它运行完成后我叫您。您看,得等人家运行完了腾出内存后才轮得到自己,可见程序对地址的依赖性之强。当可用内存很多但却因为某一个字节的内存被占用而让后来的程序等很久,这是很平常的事。有些开发人员等不及了,干脆把程序中的地址改成别的吧,重新编译后发现还是有某个地址被占用,还是没法上cpu运行,怎么办?再改地址…所以我估计那时的开发人员脾气都会很差,这人脾气差就容易伤肝,肝火一旺就会两鬓斑白,所以IT工程师还是很值得体恤的。

看着越来越多的程序员两鬓斑白,intel早期的工程师难以承受内心的自责,不顾自己的满头白发,熬了无数通宵之后,终于发明了“段”,即cpu访问内存用“段+偏移”的形式。这就是前面曾经讲解过访问内存用“段基址:段内偏移地址”的策略,它就是首次在8086上出现的。自那之后的cpu都是用这类思想访问内存,只是在形式上有所小改动,难怪8086如此极富盛名了。为了支持段机制,cpu中新增了段寄存器,如cs、ds、es等。

8086的地址总线是20位宽,也就是其寻址范围是2的20次方=1M。但其内部寄存器都是16位的,若用单一寄存器来寻址的话,只能访问到2的16次方等于64K的空间。

由于地址线位宽和寄存器位宽是没有必然联系的,所以大家不要觉得为什么寄存器不是20位的?这样通过寄存器寻址就能访问到1M空间了,显得多“配套”。

如8086的多种寻址方式中,有一种是基址寻址,这是用基址寄存器bx或bp来提供偏移地址。如mov [bx], 0x5;这条指令便是将立即数0x5存入ds:bx指向的内存。

大家看,bx寄存器是16位的,它最大只能表示0xFFFF的地址,也就是单一的一个寄存器无法表示20位的地址空间:1M。也许有人会说,段基址和段内偏移地址都搞到最大,都为0xFFFF。对不起,方案不成立,首先说会溢出,结果是0xFFFE,地址不增反小了个1。即使不溢出的话,其结果也只是由16位变成了17位,即两个n位的数字无论多大,其相加的结果也超不过n+1位,道理很简单,即使两个数都是n位能表示的最大数,两个相同的数相加,相当于乘以2,也就是数值上等于左移一位而已。依然无法访问20位的地址空间。也许有同学又有好建议了:cpu的寻址方式又不是仅仅这一种,上面的限制是因为寄存器是16位,只要不全部通过寄存器寻址不就行了吗。段寄存器也是寄存器,同样也是16位,既然它必须得用,那就在偏移地址上下功夫,不要把偏移地址写在寄存器里了,把它直接写成20位立即数不就行啦。如mov ax, [0x12345],这样最终的地址是ds+0x12345,肯定是20位,解决啦。不错,这种是直接寻址方式,至少道理上讲得通,这是通过编程技巧来突破这一瓶颈,能想到这一点我觉得非常nice。但是做为一个严谨的cpu,既然宣称支持通过寄存器来寻址,那就要能够自圆其说才行,不能靠程序员的软实力来克服cpu自身的缺陷。于是,一个大胆的想法出现了。

为了让16位的寄存器寻址能够访问20位的地址空间(注意啦亲,我这里一直说的是通过寄存器寻址,因为只有通过16位的寄存器去寻址才会受到16位的限制),cpu工程师定位到根本瓶颈是在段寄存器,它要是能提供20位的段地址,哪怕偏移地址是1也照样可以访问到内存的各个角落。于是,通过先把16位的段基址左移4位后变成20位,再加段内偏移地址,这样便形成了20位地址,只要保证了段基址是20位的,偏移地址是多少位都不关心了,从而突破了16位寄存器做为偏移地址而无法访问1M空间的限制。

有了20位地址便能访问到20位的空间,虽然解决了一个大问题,但是引入了一个小问题。还拿0xFFFF来说,现在能访问的最大的地址是0xFFFF:0xFFFF,经过左移段基址4位后得到的最大地址是:0xFFFF*16+0xFFFF=0xFFFF0+0xFFFF=0xFFFFF+0xFFF0=1M+16*4k-16-1=0x10FFEF。这公式有点晕是吗?其实最后结果是0x10FFEF是最重要的,前面的推算就是想告诉大家,按照新方法获取地址,可以得到的最大地址是1M+64K-16字节,因为这是空间范围,所以要减去1得到地址范围。

大家看到了,当初费了好大周折才搞定了能够访问20位地址空间,现在反而有点过了,过头的原因是段基址为0xFFFF0,偏移地址应该小于等于F就对啦,而这个偏移地址却是0xFFFF,超出了0xFFF0的空间,也就是多出来的64K-16字节,这部分内存就是传说中的高端内存区HMA(High Memory Area)。可是这部分内存不存在,怎么处理呢。

答案说出来吓你一跳:不用处理,哈哈。您想,8086一共就20条地址,地址线是从0开始的,即A0~A19,所以其地址空间才是1M的啊。内存地址0xFFFFF+是要用到A20地址线,可是8086它没有啊,只能接收20位长的地址。所以由于超过了20位而产生的进位,就给丢掉了。其作用相当于把地址对1M取模了。举例,如0xFFFFF+2,理论上是变成了0x100001。但由于只能容纳20位长的数据,所以最终结果是0x00001。这是地址回卷的效果:即超过最大范围后,从0重新开始计数。回卷英文称为wrap-around,示意如图

 

这就引出了从实模式到保护模式要打开A20地址线的问题,不过这部分在讲保护模式时咱们再说。兄弟们下次再来玩儿哟。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439862.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4.深度学习练习:Building your Deep Neural Network: Step by Step(强烈推荐)

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ fter this assignment you will be able to: Use non-linear units like ReLU to improve your modelBuild a d…

一步步编写操作系统21 x86虚拟机bochs 跟踪bios

为了让大家更好的理解bios是怎样被执行的,也就是计算机中第一个软件是怎样开始的,咱们还是先看下图3-17。在图的上面第5行,显示的是下一条待执行的指令,这是程序计数器(PC)中的值,在x86上的程序…

【CodeForces - 361D】Levko and Array (二分,dp)

题干: Levko has an array that consists of integers: a1, a2, ... , an. But he doesn’t like this array at all. Levko thinks that the beauty of the array a directly depends on value c(a), which can be calculated by the formula: The less value…

5.深度学习练习:Deep Neural Network for Image Classification: Application

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ After this assignment you will be able to: Build and apply a deep neural network to supervised learning…

【CodeForces - 689D】Friends and Subsequences(RMQ,二分 或单调队列)

题干: Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows? Every one of them has an integer seque…

6.深度学习练习:Initialization

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1 - Neural Network model 2 - Zero initialization 3 - Random initialization(掌握&…

【CodeForces - 602D】Lipshitz Sequence(思维,单调栈,斜率单调性)

题干: A function is called Lipschitz continuous if there is a real constant Ksuch that the inequality |f(x) - f(y)| ≤ K|x - y| holds for all . Well deal with a more... discrete version of this term. For an array , we define its Lipschi…

7.深度学习练习:Regularization

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1-Package 2 - Non-regularized model 3 - L2 Regularization(掌握) 4-Dropou…

深入详解JVM内存模型与JVM参数详细配置

本系列会持续更新。 JVM基本是BAT面试必考的内容,今天我们先从JVM内存模型开启详解整个JVM系列,希望看完整个系列后,可以轻松通过BAT关于JVM的考核。 BAT必考JVM系列专题 1.JVM内存模型 2.JVM垃圾回收算法 3.JVM垃圾回收器 4.JVM参数详解 5…

8.深度学习练习:Gradient Checking

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1) How does gradient checking work? 2) 1-dimensional gradient checking 3) N-dimensional gradie…

9.深度学习练习:Optimization Methods

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1 - Gradient Descent 2 - Mini-Batch Gradient descent 3 - Momentum 4 - Adam 5 - Model with dif…

一步步编写操作系统 22 硬盘操作方法

硬盘中的指令很多,各指令的用法也不同。有的指令直接往command寄存器中写就行了,有的还要在feature寄存器中写入参数,最权威的方法还是要去参考ATA手册。由于本书中用到的都是简单的指令,所以对此抽象出一些公共的步骤仅供参考之用…

10.深度学习练习:Convolutional Neural Networks: Step by Step(强烈推荐)

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1 - Packages 2 - Outline of the Assignment 3 - Convolutional Neural Networks 3.1 - Zero-Paddin…

一步步编写操作系统 23 重写主引导记录mbr

本节我们在之前MBR的基础上,做个稍微大一点的改进,经过这个改进后,我们的MBR可以读取硬盘。听上去这可是个大“手术”呢,我们要将之前学过的知识都用上啦。其实没那么大啦,就是加了个读写磁盘的函数而已,哈…

11.深度学习练习:Keras tutorial - the Happy House(推荐)

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ Welcome to the first assignment of week 2. In this assignment, you will: Learn to use Keras, a high-lev…

一步步编写操作系统 24 编写内核加载器

这一节的内容并不长,因为在进入保护模式之前,我们能做的不多,loader是要经过实模式到保护模式的过渡,并最终在保护模式下加载内核。本节只实现一个简单的loader,本loader只在实模式下工作,等学习了保护模式…

12.深度学习练习:Residual Networks(注定成为经典)

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ 目录 1 - The problem of very deep neural networks 2 - Building a Residual Network 2.1 - The identity…

13.深度学习练习:Autonomous driving - Car detection(YOLO实战)

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ Welcome to your week 3 programming assignment. You will learn about object detection using the very pow…

14.深度学习练习:Face Recognition for the Happy House

本文节选自吴恩达老师《深度学习专项课程》编程作业,在此表示感谢。 课程链接:https://www.deeplearning.ai/deep-learning-specialization/ Welcome to the first assignment of week 4! Here you will build a face recognition system. Many of the i…

java Integer 源码学习

转载自http://www.hollischuang.com/archives/1058 Integer 类在对象中包装了一个基本类型 int 的值。Integer 类型的对象包含一个 int 类型的字段。 此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类…