操作系统中为什么要分段

怎样通俗的理解操作系统中内存管理分页和分段? - 知乎9被浏览<strong class="NumberBoard-itemValue" title="分享邀请回答61 条评论分享收藏感谢收起看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?> 博客详情
首先,程序不是一定要分段才能运行的,分段只是为了使程序更加优美。就像用饭盒装饭菜一样,完全可以将很多菜和米饭混合在一起,或者搅拌成一体,哈哈,但这样可能就没什么胃口啦。如果饭盒中有好多小格子,方便将不同的菜和饭区分存放,这样会让我们胃口大开增加食欲。
x86平台的处理器是必须要用分段机制访问内存的,正因为如此,处理器才提供了段寄存器,用来指定待访问的内存段起始地址。我们这里讨论的程序代码中的段(用section或segment来定义的段,不同汇编编译器提供的关键字有所区别,功能是一样的)和内存访问机制中的段本质上是一回事。在硬件的内存访问机制中,处理器要用硬件--段寄存器,指向软件--程序代码中用section或segment以软件形式所定义的内存段。
分段是必然的,只是在平坦模型下,硬件段寄存器中指向的内存段为最大的4GB,而在多段模式下编程,硬件段寄存器中指向的内存段大小不一。
对于在代码中的分段,有的是操作系统做的,有的是程序员自己划分的。如果是在多段模型下编程,我们必然会在源码中定义多个段,然后需要不断地切换段寄存器所指向的段,这样才能访问到不同段中的数据,所以说,在多段模型下的程序分段是程序员人为划分的。如果是在平坦模型下编程,操作系统将整个4GB内存都放在同一个段中,我们就不需要来回切换段寄存器所指向的段。对于代码中是否要分段,这取决于操作系统是否在平坦模型下。
一般的高级语言不允许程序员自己将代码分成各种各样的段,这是因为其所用的编译器是针对某个操作系统编写的,该操作系统采用的是平坦模型,所以该编译器要编译出适合此操作系统加载运行的程序。由于处理器支持了具有分页机制的虚拟内存,操作系统也采用了分页模型,因此编译器会将程序按内容划分成代码段和数据段,如编译器gcc会把C语言写出的程序划分成代码段、数据段、栈段、.bss段、堆等部分。这会由操作系统将编译器编译出来的用户程序中的各个段分配到不同的物理内存上。对于目前咱们用高级语言编码来说,我们之所以不用关心如何将程序分段,正是由于编译器按平坦模型编译,而程序所依赖的操作系统又采用了虚拟内存管理,即处理器的分页机制。像汇编这种低级语言允许程序员为自己的程序分段,能够灵活地编排布局,这就属于人为将程序分成段了,也就是采用多段模型编程。
这么说似乎不是很清楚,一会再用例子和大伙儿解释就明白了。在这之前,先和大家明确一件事。
CPU是个自动化程度极高的芯片,就像心脏一样,给它一个初始的收缩,它将永远地跳下去。突然想到Intel的广告词:给你一颗奔腾的心。
只要给出CPU第一个指令的起始地址,CPU在它执行本指令的同时,它会自动获取下一条的地址,然后重复上述过程,继续执行,继续取址。假如执行的每条指令都正确,没有异常发生的话,我想它可以运行到世界的尽头,能让它停下来的唯一条件就是断电。
它为什么能够取得下一条指令地址?也就是说为什么知道下一条指令在哪里。这是因为程序中的指令都是挨着的,彼此之间无空隙。有同学可能会问,程序中不是有对齐这回事吗?为了对齐,编译器在程序中塞了好多0。是的,对齐确实是让程序中出现了好多空隙,但这些空隙是数据间的空隙,指令间不存在空隙,下一条指令的地址是按照前面指令的尺寸大小排下来的,这就是Intel处理器的程序计数器cs:eip能够自动获得下一条指令的原理,即将当前eip中的地址加上当前指令机器码的大小便是内存中下一条指令的起始地址。即使指令间有空隙或其他非指令的数据,这也仅仅是在物理上将其断开了,依然可以用jmp指令将非指令部分跳过以保持指令在逻辑上连续,我们在后面会通过实例验证这一原理。
为了让程序内指令接连不断地执行,要把指令全部排在一起,形成一片连续的指令区域,这就是代码段。这样CPU肯定能接连不断地执行下去。指令是由操作码和操作数组成的,这对于数据也一样,程序运行不仅要有操作码,也得有操作数,操作数就是指程序中的数据。把数据连续地并排在一起存储形成的段落,就称为数据段。
指令大小是由实际指令的操作码决定的,也就是说CPU在译码阶段拿到了操作码后,就知道实际指令所占的大小。其实说来说去,本质上就是在解释地址是怎么来的。这部分在第3章中的"什么是地址"节中有详解。
给大家演示个小例子,代码没有实际意义,是我随便写的,只是为方便大家理解指令的地址,代码如下。
code_seg.S
mov&ds,ax &
mov&ax,[var]&& &
jmp&label &
var&dw&0x99 &
本示例一共就5行,简单纯粹为演示。将其编译为二进制文件,程序内容是: &
8E&D8&A1&07&00&EB&FE&99&00&
就这9个字节的内容,有没有觉得一阵晕炫。如果没有,目测读者兄弟的技术水平远在我之上,请略过本书。
其实这9个字节的内容就是机器码。为了让大家理解得更清晰,给大家列个机器码和源码对照表,见表0-1。
表0-1 机器码和源码对照表 &
mov ds,ax
mov ax,[0x7]
jmp short 0x5
var dw 0x99
表0-1第1行,地址0处的指令是"mov ds,ax",其机器码是8ED8,这是十六进制表示,可见其大小是2字节。前面说过,下一条指令的地址是按照前面指令的尺寸排下来的,那第2行指令的起始地址是0+2=2。在第2行的地址列中,地址确实是2。这不是我故意写上去的,编译器真的就是这样编排的。第2列的指令是"mov ax,[0x7]"(0x7是变量var经过编译后的地址),其机器码是A10700,这是3字节大小。所以第3条指令的地址是2+3=5。后面的指令地址也是这样推算的。程序虽然很短,但麻雀虽小,五脏俱全,完美展示了程序中代码紧凑无隙的布局。
现在大伙儿明白为什么CPU能源源不断获取到指令了吧,如前所述,原因首先是指令是连续紧凑的,其次是通过指令机器码能够判断当前指令长度,当前指令地址+当前指令长度=下一条指令地址。
上面给出的例子,其指令在物理上是连续的,其实在CPU眼里,只要指令逻辑上是连续的就可以,没必要一定得是物理上连续。所以,明确一点,即使数据和代码在物理上混在一起,程序也是可以运行的,这并不意味着指令被数据"断开"了。只要程序中有指令能够跨过这些数据就行啦,最典型的就是用jmp跳过数据区。
比如这样的汇编代码:
&jmp&start&&&&;跳转到第三行的start,这是CPU直接执行的指令 &
&var&dd&&1&&&&;定义变量var并赋值为1。分配变量不是CPU的工作&& &
&&&&&&&&&&&&&&&&&&;汇编器负责分配空间并为变量编址 &
start:&&&&&;标号名为start,会被汇编器翻译为某个地址 &
mov&ax,0&&&&;将ax赋值为0 &
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?8系统中,存储器为什么要分段,一个段的最大和最小各为多少字节_百度知道
8系统中,存储器为什么要分段,一个段的最大和最小各为多少字节
我有更好的答案
8086CPU的数据总线是16位。地址总线的宽度不一定要与ALU的宽度相同。因为ALU的宽度是固定的,它受限于当时的工艺水平,当时只能制造出16位的ALU;但地址总线不一样,它可以设计得更宽。如果地址总线太窄的话,可寻址范围会很小。如果地址总线设计为16位的话,可寻址空间是2^16=64KB,这在当时被认为是不够的;Intel最终决定要让8086的地址空间为1M,也就是20位地址总线。把内存分为很多段,每一段有一个段基址,当然段基址也是一个20位的内存地址。不过段寄存器仍然是16位的,它的内容代表了段基址的高16位,这个16位的地址后面再加上4个0就构成20位的段基址。这样,一个完整的物理内存地址就由两部分组成,高16位的段基址和低16位的段内偏移量,当然它们有12位是重叠的,它们两部分相加在一起,才构成完整的物理地址。
采纳率:72%
分段的意义将存储单元的实际地址(20位)分成二部分来表示,即段的起始地址和段内的偏址地址二者均可用16位来表示,从而实现了对20位物理地址的描述、存储、操作、形成段寄存器寻址范围为64k字节以下是2个系统的资料微处理器 8086是Inter系列的16位微处理器,芯片上有2.9万个晶体管,采用 HMOS工 艺制造,用单一的+5V电源,时钟频率为5MHz~10MHz。 8086有16根数据线和20根地址线,它既能处理16位数据,也能处理8位数据。可 寻址的内存空间为1MB. Inter公司在推出8086的同时,还推出了一种准16位微处理器的内部寄存器,运算部件及内部数据总线都是按16位设计的,单外部数据总线只有8条。推出8086的主要目的是为了与当时已有的一套Inter外部设备接口芯片直接兼容使用。在寄存器结构,编程结构,存储器组织及I/O端口组织方面是完全一样的或稍有差别,在本节中,对其差别之做出说明。 1.3.1 的寄存器结构 图1-3示出了的寄存器结构 1. 数据寄存器 数据寄存器为图中最上边所示的4个寄存器AX,BX,CX,DX。这些寄存器用以暂时保存计算过程中所得到的操作数及结果。他能处理16位数,也能处理8位数,当处理8位数时,这4个16位寄存器作为8个8为寄存器AH,AL,BH,BL,CH,CL,DH,DL来使用。 这4个数据寄存器除了作为通用寄存器以外,还有各自的专门用途: AX(accumulator)做累加器用,是算术运算的主要寄存器。AX还用在字乘和字除法中,此外,所有的I/O指令都是以AX为中心与外部设备进行信息传送; BX(base)在计算寄存器地址时,常用做基值寄存器; CX(count)再串操作指令及循环中用做计数器; DX(data)在字乘法,字除法运算中,将DX,AX组合成一个双字长数,DX用来存放高16位数。另外,在间接的I/O指令中,DX用来指定I/O端口地址 2. 指针寄存器及变址寄存器 指针寄存器包括堆栈寄存器SP(stack pointer)和基数指针寄存器BP(base pointer),变 值寄存器包括源变址寄存器SI(source index)和目的变值寄存器DI(destination index)。这 4个寄存器都是16位寄存器,这些寄存器在运算过程中也可以用来存放操作数(只能 以字为单位),但经常的用途是在段内寻址时提供偏移地址,SP,BP一般与段寄存器SS 联用,以确定堆栈寄存器中某一单元的地址,SP用以指示栈顶的偏移地址,而BP可 作为堆栈区中的一个基地址,用以确定在堆栈中的操作数地址。SI,DI一般与段寄存器 DS联用,以确定数据段中某一存储单元的地址,SI,DI具有自动增量和自动减量的功能, 这一点使在串操作指令中用做变址非常方便,SI作为隐含的源变址DS联用,DI作为 隐含的目的变址和ES连用,从而达到在数据段和附加段中寻址的目的 3. 段寄存器 一共有4个段地址寄存器,他们是: CS(code segment register)16位代码段寄存器 DS(data segment register)16位数据段寄存器 SS(stack segment register)16位堆栈段寄存器 ES(extra segment register )16为附加段寄存器 下面将要讲到,在IBM PC机中采用存储器地址分段的办法,使能寻址1MB的内存。而段寄存器就是用来存放段地址的,CS段寄存器用来存放当前正在运行的程序;DS段寄存器用来存放当前运行的数据,若程序中使用了段操作指令,源操作数也 存放在数据段中,SS段寄存器规定了堆栈所处的区域;ES段寄存器用来存放辅助数据 ,因ES是一个附加的数据段,在执行串操作指令时,目的操作数也一般存放在ES段中。 4. 控制寄存器 IP(instruction pointer)是指令指针寄存器,是一个16位寄存器,用来存放代码段中的偏移地址。他与CS连用才能确定下一条指令的地址,根据这一地址,控制器从指定的存储器中,取出下一条要执行的指令,并修改IP,以便指向下一条要执行的指令。可见IP 寄存器是用来控制指令系列的执行流程的。 PSW(processor status word)是状态标志寄存器,也是一个16位寄存器,我们将在本节后面加以介绍。 上面介绍的这些寄存器在计算机中有非常重要的作用,在运算过程中,这些寄存器起着存储器的作用,但存取速度比存储器快得多。 1.3.2 的编程结构 所谓编程结构是指从使用者看到的结构,这是一种按功能划分的结构,这种结构与CPU内部的实际物理结构当然是有区别的。 8086的编程结构见图1-4。他分两部分。即总线接口部分BIU(bus interface unit)和执行部件EU(execution unit). 总线接口部分负责与存储器,外设端口传送数据。具体讲,总线接口部分从内存中取出指令送到指令队列时,CPU执行指令时,所需的操作数也由总线接口部分从指定的内存单元或外设端口取来,传送给执行部分去执行,反过来,执行部分的操作结果也通过 总线接口传送到指定的内存单元或外设端口中去。 总线接口部件由下面4部分组成:4个段寄存器,指令指针寄存器IP,20位的地址加法器及6个字节的指令队列。 地址加法器的作用是产生20个地址。上面提到,内部所有的寄存器都是16位的,可用20位地址去寻址1MB的内存空间,这就需要地址加法器根据16 寄存器提供的信息,计算出20位物理地址,具体算法将在本节后面讲述存储器组织时加以介绍。 对总线接口部分需说明的一点是,8086的指令队列为6个字节,而8088的指令队列为4个字节。不管是8086,还是8088,都会在执行指令的同时,从内存中取出下面一条或几条指令,取来的指令依次放在指令队列中,按顺序放,并按顺序到EU中去执行。执行部分EU的功能负责指令的执行。 执行部件包括:4个数据寄存器,2个指针寄存器,2个变值寄存器,1个状态标志寄存器和一个算术逻辑单元。 从编程结构可看出,由于总线接口部分和执行部分是分开的,每当EU执行一条指令时,造成指令队列空出2个或空出一个指令字节时 ,BIU马上从内存中取出下面一条或几条指令,以添满他的指令队列。这样,一般情况下,CPU在执行完一条指令后,便可马上执行下一条指令,不像以往8位CPU那样,执行完一条指令后,需等待下一条指令 1.3.3 的存储器组织 1. 存储单元的地址和内容 2. 在计算机中用以存储信息的基本单位是一个二进制位,每8个组成一个字节参考资料:网上论坛
系统中,存储器为什么要分段?一个段最大为多少字节?最小为多少字节?
解:分段的主要目的是便于存储器的管理,使得可以用16位寄存器来寻址20位的内存空间。一个段最大为64KB,最小为16B。
本回答被网友采纳
1条折叠回答
为您推荐:
其他类似问题
存储器的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

 

随机推荐