`
fixopen
  • 浏览: 83914 次
文章分类
社区版块
存档分类
最新评论

关于x86系列CPU的段

阅读更多
x86系列的CPU是指最早由Intel公司生产的8086系列以及以后的后继产品,也包括了各CPU生产厂商仿制的产品。但不包括后来的各种形式的64位的CPU。
段是一个存储概念。
下面描述的主要是我的想象,你可以把它当成演义来看:),不必当真。
从8086 开始,Intel的CPU就已经是16位的了。所谓16位,是指它的数据总线,地址总线(注意,地址总线并不是如此的,后面会有详细的说明,事实上,它的地址总线是20位的),各个寄存器都是16位宽的。那真是一个简单的年代。16位地址总线意味着可以寻址64K的地址空间。甚至在那个年代,64K也有点小了。所以Intel决定(配合IBM的要求)采用20位地址总线。但这引发了一个问题,那就是:指令集如何设置?要知道,20位比16位多了4个位,这四个位放在何处?寄存器都是16位的!聪明的Intel的工程师开始想到了一个办法(我估计是受DEC的启发,它的CPU就是分段式的内存,不过, Intel的分段跟他还是有很大区别的,DEC的是不重叠的分段,而Intel的分段可以重叠),就是把地址空间分成两部分,一部分叫作段基址,一部分叫作段内地址。段内地址就是原始的16位地址,所以,段的大小最大是64K,那么段基址怎么办?我们知道,段基址要在20位的地址空间中(也就是1M的地址空间)表示一个地址,最合理的选择就是20位。但是,Intel的工程师当时认为,在一个16位的CPU中放置一个20位的寄存器不合情理,所以采用了一个聪明的偷懒办法。用一个16位的寄存器表达一个低4位为零的20位地址。说得明确一点,我用16进制表示,一个16位的寄存器,其值为NNNN,那么我们就把它看成NNNN0这样一个地址。这就是段基址寄存器。简单的叫做段寄存器。在我们想访问1M地址空间中的任意一个地址区域的时候,我们可以把段寄存器的值调整的靠近(所谓的靠近,也就是比这个地址空间小,但是不小于64K的某个地方)这个地址空间,然后通过段基址和段内地址之和,就可以访问1M内任意的地址空间了。修整段寄存器地址的这个动作叫作段切换。段内地址仍然是16位长,这也限制了段的长度是64K。看到这儿,你或许会想起些什么,或许会对所谓的近指针、远指针的概念有了一些回忆。哈哈。机制描述完了,我们开始看看这个设计引发的一些有趣的限制和问题。首先,段基址被限定为低4位为0,也就是NNNN0这种形式,那么,段基址一定是16的整数倍。呵呵,这个16被称作para(paragraph,段!注意,我们上面所描述的段被Intel 的工程师称为segment)。其次,由于FFFF0 + FFFF寻址的地址已经大于1M了(事实上,整整比1M大了一个segment的长度,64K),而实际上20位地址总线确实只能寻址1M的地址空间,这就说明了我们Intel工程师的这个设计其实没有达标!呵呵,确实没有想到会有这么一个问题。后来,应该是某个Intel的心理稍微有点变态的家伙说:我们让他回环吧。一开始,估计大家都觉得很失败,后来,大家都不禁被这个想法逗乐了,回环就这样被确定下来了。我说说回环是什么。很有意思。由于段基址+段内地址可以表达超过1M的地址空间,而地址总线只能寻址1M的地址空间,所以,所有超过1M地址空间的地址都减去1M。也就是说,所有大于1M的地址空间都重新从0开始计算,就好像又绕回来了一样。这就是回环。
8086CPU内部有5?个段寄存器。也就是说,同一时间我们可以维持5个段的存在。如果我们需要多于5个段的地址空间,段切换就行了。
这是段的缘起。
由于80186是失败的,而且可以到手的资料少得可怜,我就掠过去不说,80286问世了。她第一次引入了保护。我们想一下,由于我们可以把内存分段使用,所以似乎我们也可以简单的规定对某个段我们有什么可能的权利。比如:该段是TEXT段,只可以执行,或者该段是RDATA段,只能被读取什么的。所以,给最初的段机制加上保护似乎是顺理成章的事情。但是,286在加入保护这个问题上考虑的太少了,以至于其实是不完善的。
我们仔细的分析一下。由于段是在para的边界指定的。同时,只要在para的边界上,我们就可以指定一个段,再次强调,para是16。这说明:两个不同基址的段相差最少可以是 16。而段的最大长度却可以使64K。这回导致什么?这会导致段重叠。也就是说,一个真实的地址空间的地址,可以同时隶属于多个段。那么我们对它的保护是什么样子的?所有段的可访问性的总和?最小可访问性?没有什么定论。所以说,通过段进行存储空间的保护,在Intel的CPU上,学理不太通顺(我并不是要否定段保护,相反,完善的段保护机制非常有用,可惜,在x86的机器上行不通)。在x86的机器上,我们缺少了一些东西,一般认为,我们要加上段界限,同时禁止段重叠,才能真正的实施段保护。当然,286也确实实施了一定的保护,所以286的段切换要比8086代价高。原因自然是段切换需要切换的场景信息更多的缘故。
我上面的描述其实并不是事实,或者至少有一部分不是事实。那就是:286中的段寄存器存放的不再是简单的段基址了。它存放的是一个叫做段选择子的东西,这个东西指向存储空间中的段描述符表中的某一项,或者简单的说,指向段描述符。段描述符里面存放的才是真正的段基址什么的。用比较直白的术语,我们说它引入了一重间接性。
386出场了,看到别的CPU的寻址空间和OS都在飞速扩张,Intel终于搞出来一个32位的CPU出来。32位的地址空间逻辑上可以寻址4G的存储系统。简单的说,我们可以认为段内地址扩张成32位的了,但是段这个概念以及其实现方式跟286没有太大差别。386引入了一个页的概念,不过这与我们的主题无关。
我们说说OS方面的发展。由于地址空间扩大,而物理内存并没有同比例的扩大。(注:16 位扩展成32位,地址空间增加为原来的65536倍,就算从20位增加为32位,地址空间也增加了4096倍)。物理空间增加了大约500倍左右。这中间有一个巨大的差值。聪明的人们于是搞出来一个叫做虚拟内存的东西。希望能够尽量的使用地址空间。基本的策略就是用硬盘(或者别的外部存储设备)的一部分假装是内存。这样做有什么好处呢?这得从程序的特性说起,一个程序,不可能同时访问地址空间内所有的数据,而是相反,一段时间内集中在一个区域。这个特性叫做局部性。根据局部性,对于需要立即访问的放在物理内存中,不需要立即访问的放在虚拟内存中,等到需要访问时,再装入内存中以供访问。这简化了应用程序的逻辑,应用程序只需要按照自己的意图是用全部的地址空间就行了。这种物理内存和虚拟内存之间的倒腾由OS完成。实现虚拟内存需要CPU的支持(其实如果没有也行,不过性能根本就没办法保证),现在常用的甚至是唯一的方式就是内存分页,这个倒腾的过程也因而叫做换页。逻辑上,我们可以用分段来实现虚拟内存的(想想前面提到的段切换),但是由于段的不规整性(页的大小是一致的,规整的,而段不是,参见前面的描述),实现相对复杂,需要CPU的支持更多,性能更难以保证。所以,现代OS全都不约而同地采用分页的方式实现虚存,而没有采用分段的方式。
那么,对于x86这种既支持分段,有支持分页的CPU来说,OS究竟怎么办?其实,很简单,简单的忽略分段就行了。那位说了,这不是你想忽略就忽略的吧。x86CPU访问存储空间地址的时候就是采用段基址+段内地址的呀,这是硬件的实现,岂是我们可以忽略的?呵呵,如果我们把段基址规定成0怎么样?这样我们就可以不关心段了。是的,现代OS都是这样做的。
比如:Windows系统,其几个段寄存器(存放的是段选择子了)都是指向28(好像是)号段描述符,而28号段描述符都是0基址的。
持平的说,x86系列CPU的段机制设计的还算是比较好的,颇有巴洛克的味道,跟Intel第一次64位CPU的尝试安腾一样。呵呵。
上面所说的一切都是记忆,不提供任何正确性担保,聪明人都不会看它的,当然,看了的人更聪明。
分享到:
评论

相关推荐

    X86 CPU在段式管理下的地址形成机制

    80x86系列CPU支持段式管理,这是一种历史遗留下来的存储管理方式,主要是因为早期的CPU设计。在段式管理中,程序员使用的地址形式是“段基址:偏移量”,这被称为虚拟地址,是二维的。经过段地址翻译,虚拟地址转化为...

    Intel X86系列CPU模拟器的研究与实现.pdf

    《Intel X86系列CPU模拟器的研究与实现》这篇文章主要探讨了如何使用Simulink构建Intel X86系列CPU的模拟器,这是一种用于理解和验证CPU内部操作的重要工具。CPU模拟器在计算机科学研究和教育中扮演着关键角色,它使...

    32位 64位CPU X86详解

    【标题】和【描述】提到的主题是关于32位和64位CPU,特别是X86架构的详解。X86是一种由Intel首次开发的微处理器架构,后来被其他厂商如AMD等采用并发展,成为个人计算机领域最广泛使用的处理器架构。 【x86架构】...

    Intel_X86_CPU系列的寄存

    Intel_X86_CPU系列的寄存

    X86CPU入门调研报告

    【X86CPU入门调研报告】 X86架构CPU是当前个人电脑和服务器领域的主流选择,其中Intel和AMD是两大主导厂商。X86架构以其高性能、高速度和良好的兼容性著称,广泛应用于各种计算任务。然而,近年来国产X86 CPU也开始...

    深入PC的核心:了解X86 CPU.pdf

    然而,当前市场上的主流X86系列CPU仍然是IA-32架构,因为Intel的64位Itanium(IA-64)正在逐步被新的64位扩展(如x86-64,也称为EM64T)取代。 在X86系列CPU的主要生产商中,Intel占据主导地位,其产品线包括...

    X86 CPU解码工具源码

    X86 CPU解码工具是针对这种架构的处理器设计的一种实用软件,其核心功能是将CPU执行的机器指令转化为人类可读的汇编语言代码。 这个源码包包含以下几个关键文件: 1. **DecodeCPUCode.cpp**:这是主程序源文件,...

    英特尔X86系列处理器与ARM系列处理器性能和参数对比.doc

    自从1971年 Intel诞生了第一个微处理器——4004开始,微处理器得到了飞速的发展,在这短短的四十年的时间里有很多家公司生产过无数种型号的微处理器,但是最终只有Inter公司和ARM公司生存下来并发展成为世界最主要的...

    vxwork操作系统源代码(arm,x86等cpu).zip

    关于ARM架构,VxWorks提供了针对各种ARM处理器系列的驱动和库,比如Cortex-A、Cortex-R以及Cortex-M系列。开发者可以查看并修改这些驱动,以适应新的或特殊的硬件需求。例如,对于网络通信,可能需要定制以太网控制...

    历史上的X86CPU(一).pdf

    X86是Intel从8086处理器开始的一个系列,它并不是一个专业的技术术语,而是对Intel处理器家族的通俗称呼。8086处理器在1978年6月发布,标志着16位CPU时代的到来,并且奠定了x86架构的基础,这是一种成熟的CPU指令...

    ARM微处理器和x86系列处理器的区别

    ### ARM微处理器与x86系列处理器的主要区别 #### 指令集体系结构 - **RISC vs CISC** - **RISC (Reduced Instruction Set Computer)**:ARM处理器采用RISC架构,其特点在于拥有较少数量但功能强大的指令集。这有助...

    Intel系列CPU指令速查手册

    《Intel系列CPU指令速查手册》是一份详细记录Intel系列CPU指令集的参考资料,对于开发者、程序员和系统管理员来说,是理解和使用Intel处理器指令的重要工具。手册中的指令涵盖各种操作,包括数据处理、控制流、输入...

    Anaconda3-2022.10-MacOSX-x86-64 intel和amd系列CPU专用

    Anaconda3-2022.10-MacOSX-x86_64 intel和amd系列CPU专用 Anaconda 是一个广泛使用的开源Python发行版,特别为数据科学、机器学习、人工智能领域的专业人士和爱好者设计。它不仅仅包括Python语言本身,还打包了超过...

    cpp-libcpuid用于x86CPU检测和特征提取的小型C库

    cpp-libcpuid是一款专门针对x86架构CPU进行检测和特征提取的小型C++库。这个库的核心功能是获取CPU的相关信息,包括但不限于制造商、型号、频率、缓存结构、指令集支持以及特定的硬件特性。在软件开发中,这些信息...

    历史上的x86CPU(二).pdf

    本文主要探讨的是x86系列的CPU,这是一个由Intel公司开创并广泛应用于个人计算机的处理器架构。 x86架构起源于1978年发布的8086处理器,该处理器以16位指令集为基础。随着技术的发展,x86家族经历了多次迭代,如...

    现代X86汇编语言程序设计Modern X86 Assembly Language Programming

    X86汇编语言是针对Intel和AMD等公司制造的X86系列处理器的低级编程语言,它是硬件层面上与CPU交互的直接方式,对于理解计算机底层工作原理和进行性能优化至关重要。 X86汇编语言的特点在于它的指令集,包括数据处理...

    torch_cluster-1.6.0+pt113cpu-cp310-cp310-linux_x86_64.whl.zip

    《torch_cluster-1.6.0+pt113cpu-cp310-cp310-linux_x86_64.whl.zip:深度学习中的图神经网络库》 在深度学习领域,图神经网络(Graph Neural Networks, GNNs)已经成为处理非欧几里得数据的重要工具。torch_...

    OS_CPU_A.rar_x86

    描述中提到,“好不容易才找到的”可能意味着这份资料的稀缺性和价值,而“是基于X86的汇编代码”进一步确认了内容的核心——它是关于X86架构的汇编语言编程。“仅供学习或查找使用”则提示这可能是教学材料或者供...

Global site tag (gtag.js) - Google Analytics