还剩18页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
寄存器目录[隐藏j__ascript:void0]寄存器定义http://baike.baidu.com/view/
6159.html\l1#1寄存器用途http://baike.baidu.com/view/
6159.html\l2#2数据寄存器http://baike.baidu.com/view/
6159.html\l3#3寄存器分类http://baike.baidu.com/view/
6159.html\l4#4 HYPERLINKhttp://imgsrc.baidu.com/baike/pic/item/73ca5910d7918defc3ce79b
3.jpg\t_blankINCLUDEPICTUREhttp://imgsrc.baidu.com/baike/abpic/item/73ca5910d7918defc3ce79b
3.jpg\*MERGEFORMAT英文名称Register[编辑本段http://baike.baidu.com/view/
6159.html\l#]寄存器定义 寄存器是__处理器http://baike.baidu.com/view/
14045.htm\t_blank内的组成部份寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址在__处理器的控制部件中,包含的寄存器有指令寄存器http://baike.baidu.com/view/
178142.htm\t_blankIR和程序计数器http://baike.baidu.com/view/
178145.htm\t_blankPC在__处理器的算术及逻辑部件中,包含的寄存器有累加器http://baike.baidu.com/view/
471649.htm\t_blankACChttp://baike.baidu.com/view/3___
59.htm\t_blank 寄存器是内存阶层中的最顶端,也是系统获得操作资料的最快速途径寄存器通常都是以他们可以保存的位元数量来估量,举例来说,一个“8位元寄存器”或“32位元寄存器”寄存器现在都以寄存器档案的方式来实作,但是他们也可能使用单独的正反器、高速的核心内存、薄膜内存以及在数种机器上的其他方式来实作出来 寄存器通常都用来意指由一个指令之输出或输入可以直接索引到的暂存器群组更适当的是称他们为“架构寄存器” 例如,x86指令及定义八个32位元寄存器的__,但一个实作x86指令集的CPU可以包含比八个更多的寄存器 寄存器是CPU内部的元件,寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快[编辑本段http://baike.baidu.com/view/
6159.html\l#]寄存器用途
1.可将寄存器内的数据执行算术及逻辑运算;
2.存于寄存器内的地址可用来指向内存的某个位置,即寻址;
3.可以用来读写数据到电脑的周边设备[编辑本段http://baike.baidu.com/view/
6159.html\l#]数据寄存器 8086有14个16位寄存器,这14个寄存器按其用途可分为1通用寄存器、2指令指针、3标志寄存器和4段寄存器等4类 1通用寄存器有8个又可以分成2组一组是数据寄存器4个另一组是指针寄存器及变址寄存器4个. 数据寄存器分为: AHAL=AXaccumulator累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数另外所有的I/O指令都使用这一寄存器与外界设备传送数据. BHBL=BXbase基址寄存器,常用于地址索引; CHCL=CXcount计数寄存器,常用于计数;常用于保存计算值如在移位指令循环loop和串处理指令中用作隐含的计数器. DHDL=DXdata数据寄存器,常用于数据传递 他们的特点是这4个16位的寄存器可以分为高8位:AHBHCHDH.以及低八位ALBLCLDL这2组8位寄存器可以分别寻址,并单独使用 另一组是指针寄存器和变址寄存器,包括 SP(StackPointer)堆栈指针,与SS配合使用,可指向目前的堆栈位置; BP(BasePointer)基址指针寄存器,可用作SS的一个相对基址位置; SI(Sour__Index)源变址寄存器可用来存放相对于DS段之源变址指针; DI(DestinationIndex)目的变址寄存器,可用来存放相对于ES段之目的变址指针 这4个16位寄存器只能按16位进行存取操作,主要用来形成操作数的地址,用于堆栈操作和变址运算中计算操作数的有效地址 2指令指针IPInstructionPointer 指令指针IP是一个16位专用寄存器,它指向当前需要取出的指令字节,当BIU从内存中取出一个指令字节后,IP就自动加1,指向下一个指令字节注意,IP指向的是指令地址的段__址偏移量,又称偏移地址OffsetAddress或有效地址EA,EffectiveAddress 3标志寄存器FRFlagRegister 8086有一个18位的标志寄存器FR,在FR中有意义的有9位,其中6位是状态位,3位是控制位 OF溢出标志位OF用于反映有符号数加减运算所得结果是否溢出如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0 DF方向标志DF位用来决定在串操作指令执行时有关指针寄存器发生调整的方向 IF中断允许标志IF位用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求具体规定如下
1、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;
2、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求 TF跟踪标志TF该标志可用于程序调试TF标志没有专门的指令来设置或清楚
(1)如果TF=1,则CPU处于单步执行指令的工作方式,此时每执行完一条指令,就显示CPU内各个寄存器的当前值及CPU将要执行的下一条指令
(2)如果TF=0,则处于连续工作模式 SF符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号运算结果为正数时,SF的值为0,否则其值为1 __零标志__用来反映运算结果是否为0如果运算结果为0,则其值为1,否则其值为0在判断运算结果是否为0时,可使用此标志位 AF下列情况下,辅助进位标志AF的值被置为1,否则其值为0
1、在字操作时,发生低字节向高字节进位或借位时;
2、在字节操作时,发生低4位向高4位进位或借位时 PF奇偶标志PF用于反映运算结果中“1”的个数的奇偶性如果“1”的个数为偶数,则PF的值为1,否则其值为0 CF进位标志CF主要用来反映运算是否产生进位或借位如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0 4段寄存器SegmentRegister 为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址 CS(CodeSegment)代码段寄存器; DS(DataSegment)数据段寄存器; SS(StackSegment)堆栈段寄存器; ES(ExtraSegment)附加段寄存器 当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS来指向这些起始位置通常是将DS固定,而根据需要修改CS所以,程序可以在可寻址空间小于64K的情况下被写成任意大小所以,程序和其数据组合起来的大小,限制在DS所指的64K内,这就是COM文件不得大于64K的原因8086以内存做为战场,用寄存器做为军事__,以加速工作 以上是8086寄存器的整体概况自80___开始,PC进入32bit时代,其寻址方式,寄存器大小,功能等都发生了变化 =============================以下是80___的寄存器的一些资料====================================== 寄存器都是32-bits宽 A、通用寄存器 下面介绍通用寄存器及其习惯用法顾名思义,通用寄存器是那些你可以根据自己的意愿使用的寄存器,修改他们的值通常不会对计算机的运行造成很大的影响通用寄存器最多的用途是计算 EAX通用寄存器相对其他寄存器,在进行运算方面比较常用在保护模式中,也可以作为内存偏移指针(此时,DS作为段寄存器或选择器) EBX通用寄存器通常作为内存偏移指针使用(相对于EAX、ECX、EDX),DS是默认的段寄存器或选择器在保护模式中,同样可以起这个作用 ECX通用寄存器通常用于特定指令的计数在保护模式中,也可以作为内存偏移指针(此时,DS作为寄存器或段选择器) EDX通用寄存器在某些运算中作为EAX的溢出寄存器(例如乘、除)在保护模式中,也可以作为内存偏移指针(此时,DS作为段寄存器或选择器) 同AX分为AHAL一样,上述寄存器包括对应的16-bit分组和8-bit分组 B、用作内存指针的特殊寄存器 ESI通常在内存操作指令中作为“源地址指针”使用当然,ESI可以被装入任意的数值,但通常没有人把它当作通用寄存器来用DS是默认段寄存器或选择器 EDI通常在内存操作指令中作为“目的地址指针”使用当然,EDI也可以被装入任意的数值,但通常没有人把它当作通用寄存器来用DS是默认段寄存器或选择器 EBP这也是一个作为指针的寄存器通常,它被高级语言编译器用以建造‘堆栈帧来保存函数或过程的局部变量,不过,还是那句话,你可以在其中保存你希望的任何数据SS是它的默认段寄存器或选择器 注意,这三个寄存器没有对应的8-bit分组换言之,你可以通过SI、DI、BP作为别名访问他们的低16位,却没有办法直接访问他们的低8位 C、段选择器 实模式下的段寄存器到保护模式下摇身一变就成了选择器不同的是,实模式下的“段寄存器”是16-bit的,而保护模式下的选择器是32-bit的 CS代码段,或代码选择器同IP寄存器稍后介绍一同指向当前正在执行的那个地址处理器执行时从这个寄存器指向的段(实模式)或内存(保护模式)中获取指令除了跳转或其他分支指令之外,你无法修改这个寄存器的内容 DS数据段,或数据选择器这个寄存器的低16bit连同ESI一同指向的指令将要处理的内存同时,所有的内存操作指令默认情况下都用它指定操作段实模式或内存作为选择器,在保护模式这个寄存器可以被装入任意数值,然而在这么做的时候需要小心一些方法是,首先把数据送给AX,然后再把它从AX传送给DS当然,也可以通过堆栈来做. ES附加段,或附加选择器这个寄存器的低16bit连同EDI一同指向的指令将要处理的内存同样的,这个寄存器可以被装入任意数值,方法和DS类似 FSF段或F选择器推测F可能是Free可以用这个寄存器作为默认段寄存器或选择器的一个替代品它可以被装入任何数值,方法和DS类似 GSG段或G选择器G的意义和F一样,没有在Intel的文档中解释它和FS几乎完全一样 SS堆栈段或堆栈选择器这个寄存器的低16bit连同ESP一同指向下一次堆栈操作push和pop所要使用的堆栈地址这个寄存器也可以被装入任意数值,你可以通过入栈和出栈操作来给他赋值,不过由于堆栈对于很多操作有很重要的意义,因此,不正确的修改有可能造成对堆栈的破坏 *注意一定不要在初学汇编的阶段把这些寄存器弄混他们非常重要,而一旦你掌握了他们,你就可以对他们做任意的操作了段寄存器,或选择器,在没有指定的情况下都是使用默认的那个这句话在现在看来可能有点稀里糊涂,不过你很快就会在后面知道如何去做 指令指针寄存器 EIP这个寄存器非常的重要这是一个32位宽的寄存器,同CS一同指向即将执行的那条指令的地址不能够直接修改这个寄存器的值,修改它的唯一方法是跳转或分支指令CS是默认的段或选择器 上面是最基本的寄存器下面是一些其他的寄存器,你甚至可能没有听说过它们都是32位宽 CR0CR2CR3控制寄存器举一个例子,CR0的作用是切换实模式和保护模式 还有其他一些寄存器,D0D1D2D3D6和D7调试寄存器他们可以作为调试器的硬件支持来设置条件断点 TR3TR4TR5TR6和TR寄存器测试寄存器用于某些条件测试[编辑本段http://baike.baidu.com/view/
6159.html\l#]寄存器分类 数据寄存器-用来储存整数数字(参考以下的浮点寄存器)在某些简单/旧的CPU,特别的数据寄存器是累加器,作为数学计算之用 地址寄存器-持有存储器地址,以及用来访问存储器在某些简单/旧的CPU里,特别的地址寄存器是索引寄存器(可能出现一个或多个) 通用目的寄存器(GPRs)-可以保存数据或地址两者,也就是说他们是结合数据/地址寄存器的功用 浮点寄存器(FPRs)-用来储存浮点数字 常数寄存器-用来持有只读的数值(例如
0、
1、圆周率等等) 向量寄存器-用来储存由向量处理器运行SIMD(SingleInstructionMultipleData)指令所得到的数据 特殊目的寄存器-储存CPU内部的数据,像是程序计数器(或称为指令指针),堆栈寄存器,以及状态寄存器(或称微处理器状态字组) 指令寄存器(instructionregister)-储存现在正在被运行的指令 索引寄存器(indexregister)-是在程序运行实用来更改运算对象地址之用 在某些架构下,模式指示寄存器(也称为“机器指示寄存器”)储存和设置跟处理器自己有关的数据由于他们的意图目的是附加到特定处理器的设计,因此他们并不被预期会成微处理器世代之间保留的标准 有关从随机存取存储器提取信息的寄存器与CPU(位于不同芯片的储存寄存器__) 存储器缓冲寄存器(Memorybufferregister) 存储器数据寄存器(Memorydataregister) 存储器地址寄存器(Memoryaddressregister)存储器型态范围寄存器(MemoryTypeRangeRegisters)
[1]
[2]实模式 1:实模式寻址采用和8086相同的16位段和偏移量,最大寻址空间1MB,最大分段64KB可以使用32位指令32位的x86CPU用做高速的8086 2:保护模式寻址采用32位段和偏移量,最大寻址空间4GB,最大分段4GBPentiumPre及以后为64GB在保护模式下CPU可以进入虚拟8086方式,这是在保护模式下的实模式程序运行环境 第一:实模式下程序的运行回顾. 程序运行的实质是什么其实很简单就是指令的执行显然CPU 是指令得以执行的硬件保障那么CPU如何知道指令在什么地方呢 对了80x86系列是使用CS寄存器配合IP寄存器来通知CPU指令在内存 中的位置. 程序指令在执行过程中一般还需要有各种数据80x86系列有DS、 ES、FS、GS、SS等用于指示不同用途的数据段在内存中的位置 程序可能需要调用系统的服务子程序,80x86系列使用中断机制 来实现系统服务 总的来说,这些就是实模式下一个程序运行所需的主要内容 (其它如跳转、返回、端口操作等相对来说比较次要) 第二保护模式---从程序运行说起 无论实模式还是保护模式,根本的问题还是程序如何在其中运行 因此我们在学习保护模式时应该时刻围绕这个问题来思考 和实模式下一样,保护模式下程序运行的实质仍是“CPU执行指令, 操作相关数据”,因此实模式下的各种代码段、数据段、堆栈段、中 断服务程序仍然存在,且功能、作用不变 那么保护模式下最大的变化是什么呢?答案可能因人而异,我的 答案是“地址转换方式”变化最大 第三地址转换方式比较 先看一下实模式下的地址转换方式,假设我们在ES中存入0x1000, DI中存入0xFFFF那么ES:DI=0x1000*0x10+0xFFFF=0x1FFFF这就是众 所周知的“左移4位加偏移” 那么如果在保护模式下呢?假设上面的数据不变ES=0x1000 DI=0xFFFF,现在ES:DI等于什么呢? 公式如下(注0x1000=_____00000000b=1000000000000) ES:DI=全局描述符表中第0x200项描述符给出的段基址+0xFFFF 现在比较一下,好象是不一样再仔细看看,又好象没什么区别! ___说没什么区别,因为我的想法是,既然ES中的内容都不是 真正的段地址,凭什么实模式下称ES为“段寄存器”,而到了保护模式 就说是“选择子”? 其实它们都是一种映射,只是映射规则不同而已在实模式下这 个“地址转换方式”是“左移4位”;在保护模式下是“查全局/局部描述表” 前者是系统定义的映射方式,后者是用户自定义的转换方式而它 影响的都是“shadowregister” 从函数的观点来看,前者是表达式函数,后者是列举式函数 实模式Fes--segment={segment|segment=es*0x10} 保护模式Fes--segment={segment|essegment∈GDT/LDT} 其中GDT、LDT分别表示全局描述符表和局部描述符表 第四保护模式基本组成 保护模式最基本的组成部分是围绕着“地址转换方式”的变化增设了 相应的机构
1、数据段 前面说过,实模式下的各种代码段、数据段、堆栈段、中断服务程 序仍然存在,我将它们统称为“数据段”,本文从此向下凡提到数据段都 是使用这个定义
2、描述符 保护模式下引入描述符来描述各种数据段,所有的描述符均为8个字 节(0-7,由第5个字节说明描述符的类型,类型不同,描述符的结构也 有所不同 若干个描述符集中在一起组成描述符表,而描述符表本身也是一种 数据段,也使用描述符进行描述所以CPU中有一个IDr索引寄存器 从现在起,“地址转换”由描述符表来完成,从这个意义上说,描述符 表是一张地址转换函数表
3、选择子 选择子是一个2字节的数,共16位,最低2位表示RPL,第3位表示查表 是利用GDT(全局描述符表)还是LDT(局部描述符表)进行,最高13位给 出了所需的描述符在描述符表中的地址(注13位正好足够寻址8K项) 有了以上三个概念之后可以进一步工作了,现在程序的运行与实模式 下完全一样!!!各段寄存器仍然给出一个“段值”,只是这个“假段值” 到真正的段地址的转换不再是“左移4位”,而是利用描述符表来完成但 现在出现一个新的问题是 系统如何知道GDT/LDT在内存中的位置呢? 为了解决这个问题,显然需要引入新的寄存器用于指示GDT/LDT在内 存中的位置在80x86系列中引入了两个新寄存器GDR和LDR,其中GDR用于 表示GDT在内存中的段地址和段限(就是表的大小),因此GDR是一个48 位的寄存器,其中32位表示段地址,16位表示段限(最大64K,每个描述 符8字节,故最多有64K/8=8K个描述符)LDR用于表示LDT在内存中的位 置,但是因为LDT本身也是一种数据段,它必须有一个描述符,且该描述 符必须放在GDT中,因此LDR使用了与DS、ES、CS等相同的机制,其中只 存放一个“选择子”,通过查GDT表获得LDT的真正内存地址 对了,还有中断要考虑,在80x86系列中为中断服务提供中断/陷阱描 述符,这些描述符构成中断描述符表(IDT),并引入一个48位的全地址 寄存器存放IDT的内存地址理论上IDT表同样可以有8K项,可是因为80x86 只支持256个中断,因此IDT实际上最大只能有256项(2K大小) 第五新要求---任务篇 前面介绍了保护模式的基本问题,也是核心问题,解决了上面的问题, 程序就可以在保护模式下运行了 但众所周知80286以后在保护模式下实现了对多任务的硬件支持我 的第一反应是___不在实模式下支持多任务,是不能还是不愿? 思考之后,我的答案是实模式下能实现多任务(也许我错了)) 因为多任务的关键是有了描述符,可以给出关于数据段的额外描述,如权 限等,进而在这些附加信息的基础上进行相应的控制,而实模式下缺乏描 述符,但假设我们规定各段的前2个字节或若干字节用于描述段的附加属性, 我觉得和使用描述符这样的机制没有本质区别,如果再附加其他机制... 基于上述考虑,我更倾向于认为任务是__于保护模式之外的功能 下面我们来分析一下任务任务的实质是什么呢?很简单,就是程序嘛!! 所谓任务的切换其实就是程序的切换!! 现在问题明朗了实模式下程序一个接一个运行,因此程序运行的 “环境”不必保存;保护模式下可能一个程序在运行过程中被暂停,转而执行 下一个程序,我们要做什么?很容易想到保存程序运行的环境就行了(想 想游戏程序的保存进度功能),比如各寄存器的值等 显然这些“环境”数据构成了一类新的数据段(即TSS)延用前面的思路, 给这类数据段设置描述符(TSS描述符),将该类描述符放在GDT中(不能 放在LDT中,因为80x86不允许)),最后再加一个TR寄存器用于查表 TR是一个起“选择子”作用的寄存器,16位 好了,任务切换的基本工作就是将原任务的“环境”存入TSS数据段,更 新TR寄存器,系统将自动查GDT表获得并装载新任务的“环境”,然后转到新 任务执行 第六附加要求---分页篇 ___叫附加要求,因为现在任务还不能很好地工作前面说过,任务 实质上是程序,不同的程序是由不同的用户写的,所有这些程序完全可能 使用相同的地址空间,而任务的切换过程一般不会包括内存数据的刷新, 不是不可能,而是如果那样做太浪费了因此必须引入分页机制才可能有效 地完成对多任务的支持 分页引入的主要目标就是解决不同任务相互之间发生地址冲突的问题 分页的实质就是实现程序__址到物理地址的映射,这也是一个“地址转换” 机制,同样可以使用前面的方案(即类似GDT的做法)首先建立页表这样 一种数据段,在80x86中使用二级页表方案,增设一个CR3寄存器用于存放 一级页表(又称为页目录)在内存中的地址,CR3共32位,其低12位总是为 零,高20位指示页目录的内存地址,因此页目录总是按页对齐的CR3作为 任务“环境”的一部分在任务切换时被存入TSS数据段中 当然还得有相应的缺页中断机制及其相关寄存器CR2(页故障线性地址寄存器) 第七总结 保护模式下增加了什么?
1、寄存器GDRLDRIDRTRCR3
2、数据段描述符表GDTLDT任务数据段TSS页表页目录二级页表
3、机制权限检测利用选择子/描述符/页表项的属性位 线性地址到物理地址的映射 第八保护模式常用名词解释 前面内容中出现过的不再解释
1、RPL选择子当中的权限位确定的权限
2、CPL特指CS中的选择子当中的权限位确定的权限
3、EPLEPL=__xRPLCPL即RPL和CPL中数值较大的,或说权限等级较小的
4、DPL描述符中的权限位确定的权限
5、PL泛指以上4种特权级
6、任务特权=CPL
7、I/O特权由EFLAGS寄存器的位
13、14确定的权限
8、一致代码段一种特殊的代码段,它在CPL=DPL时允许访问 正常的代码段在CPL=DPLRPL=DPL时才允许访问MMU MMU是Memory__nagementUnit的缩写,中文名是内存管理单元,它是__处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权
一、MMU的历史 许多年以前,当人们还在使用DOS或是更古老的操作系统的时候,计算机的内存还非常小,一般都是以K为单位进行计算,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序但随着图形界面的兴起还有用户需求的不断增大,应用程序的规模也随之膨胀起来,终于一个难题出现在程序员的面前,那就是应用程序太大以至于内存容纳不下该程序,通常解决的办法是把程序分割成许多称为覆盖块(overlay)的片段覆盖块0首先运行,结束时他将调用另一个覆盖块虽然覆盖块的交换是由OS完成的,但是必须先由程序员把程序先进行分割,这是一个费时费力的工作,而且相当枯燥人们必须找到更好的办法从根本上解决这个问题不久人们找到了一个办法,这就是虚拟存储器virtualmemory.虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上比如对一个16MB的程序和一个内存只有4MB的机器,操作系统通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了而这个16M的程序在运行前不必由程序员进行分割
二、MMU的相关概念——地址范围、虚拟地址映射为物理地址以及分页机制 任何时候,计算机上都存在一个程序能够产生的地址__,我们称之为地址范围这个范围的大小由CPU的位数决定,例如一个32位的CPU,它的地址范围是0~0xFFFFFFFF4G而对于一个64位的CPU,它的地址范围为0~0xFFFFFFFFFFFFFFFF64T.这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址与虚拟地址空间和虚拟地址相对应的则是物理地址空间和物理地址,大多数时候我们的系统所具备的物理地址空间只是虚拟地址空间的一个子集这里举一个最简单的例子直观地说明这两者,对于一台内存为256M的32bitx86主机来说,它的虚拟地址空间范围是0~0xFFFFFFFF(4G)而物理地址空间范围是0x000000000~0x0FFFFFFF(256M) 在没有使用虚拟存储器的机器上,虚拟地址被直接送到内存总线上,使具有相同地址的物理存储器被读写;而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到存储器管理单元MMU,把虚拟地址映射为物理地址 大多数使用虚拟存储器的系统都使用一种称为分页(paging)机制虚拟地址空间划分成称为页(page)的单位而相应的物理地址空间也被进行划分,单位是页桢frame.页和页桢的大小必须相同在这个例子中我们有一台可以生成32位地址的机器,它的虚拟地址范围从0~0xFFFFFFFF(4G)而这台机器只有256M的物理地址,因此他可以运行4G的程序,但该程序不能一次性调入内存运行这台机器必须有一个达到可以存放4G程序的外部存储器(例如磁盘或是FLASH)以保证程序片段在需要时可以被调用在这个例子中,页的大小为4K页桢大小与页相同——这点是必须保证的,因为内存和__存储器之间的传输总是以页为单位的对应4G的虚拟地址和256M的物理存储器,他们分别包含了1M个页和64K个页桢
三、MMU的功能
1、将虚拟地址映射为物理地址 现代的多用户多进程操作系统,需要MMU才能达到每个用户进程都拥有自己__的地址空间的目标使用MMU操作系统划分出一段地址区域在这块地址区域中每个进程看到的内容都不一定一样例如MICROSOFTWINDOWS操作系统将地址范围4M-2G划分为用户地址空间,进程A在地址0X400000(4M)映射了可执行文件,进程B同样在地址0X400000(4M)映射了可执行文件,如果A进程读地址0X400000读到的是A的可执行文件映射到RAM的内容,而进程B读取地址0X400000时,则读到的是B的可执行文件映射到RAM的内容 这就是MMU在当中进行地址转换所起的作用
2、提供硬件机制的内存访问授权 多年以来,微处理器一直带有片上存储器管理单元MMU,MMU能使单个软件线程工作于硬件保护地址空间但是在许多商用实时操作系统中,即使系统中含有这些硬件也没采用MMU 当应用程序的所有线程共享同一存储器空间时,任何一个线程将有意或无意地破坏其它线程的代码、数据或堆栈异常线程甚至可能破坏内核代码或内部数据结构例如线程中的指针错误就能轻易使整个系统崩溃,或至少导致系统工作异常 就安全性和可靠性而言,基于进程的实时操作系统RTOS的性能更为优越为生成具有单独地址空间的进程,RTOS只需要生成一些基于RAM的数据结构并使MMU加强对这些数据结构的保护基本思路是在每个关联转换中“接入”一组新的逻辑地址MMU利用当前映射,将在指令调用或数据读写过程中使用的逻辑地址映射为存储器物理地址MMU还标记对非法逻辑地址进行的访问,这些非法逻辑地址并没有映射到任何物理地址 这些进程虽然增加了利用查询表访问存储器所固有的系统开销,但其实现的效益很高在进程边界处,疏忽或错误操作将不会出现,用户接口线程中的缺陷并不会导致其它更关键线程的代码或数据遭到破坏目前在可靠性和安全性要求很高的复杂嵌入式系统中,仍然存在采无存储器保护的操作系统的情况,这实在有些____ 采用MMU还有利于选择性地将页面映射或解映射到逻辑地址空间物理存储器页面映射至逻辑空间,以保持当前进程的代码,其余页面则用于数据映射类似地,物理存储器页面通过映射可保持进程的线程堆栈RTOS可以在每个线程堆栈解映射之后,很容易地保留逻辑地址所对应的页面内容这样,如果任何线程分配的堆栈发生溢出,将产生硬件存储器保护故障,内核将挂起该线程,而不使其破坏位于该地址空间中的其它重要存储器区,如另一线程堆栈这不仅在线程之间,还在同一地址空间之间增加了存储器保护 存储器保护包括这类堆栈溢出检测在应用程序__中通常非常有效采用了存储器保护,程序错误将产生异常并能被立即检测,它由源代码进行跟踪如果没有存储器保护,程序错误将导致一些细微的难以跟踪的故障实际上,由于在扁平存储器模型中,RAM通常位于物理地址的零页面,因此甚至NULL指针引用的解除都无法检测到
四、MMU和CPU
1、X86系列的MMU INTEL出品的80___CPU或者更新的CPU中都集成有MMU.可以提供32BIT共4G的地址空间. X86MMU提供的寻址模式有4K/2M/4M的PAGE模式根据不同的CPU,提供不同的能力此处提供的是目前大部分操作系统使用的4K分页机制的描述,并且不提供AC__SSCHECK的部分 涉及的寄存器 aGDT bLDT cCR0 dCR3 eSEGMENTREGISTER 虚拟地址到物理地址的转换步骤 aSEGMENTREGISTER作为GDT或者LDT的INDEX取出对应的GDT/LDTENTRY. 注意:SEGMENT是无法取消的即使是FLAT模式下也是如此.说FLAT模式下不使用SEGMENTREGISTER是错误的.任意的RAM寻址指令中均有DEFAULT的SEGMENT假定.除非使用SEGMENTOVERRIDEPREFIX来改变当前寻址指令的SEGMENT否则使用的就是DEFAULTSEGMENT. ENTRY格式 typedefstruct { UINT16limit_0_15; UINT16base_0_15; UINT8base_16_23; UINT8ac__ssed:1; UINT8readable:1; UINT8conforming:1; UINT8code_data:1; UINT8app_system:1; UINT8dpl:2; UINT8present:1; UINT8limit_16_19:4; UINT8unused:1; UINT8always_0:1; UINT8seg_16_32:1; UINT8granularity:1; UINT8base_24_31; }CODE_SEG_DESCRIPTOR*PCODE_SEG_DESCRIPTOR; typedefstruct { UINT16limit_0_15; UINT16base_0_15; UINT8base_16_23; UINT8ac__ssed:1; UINT8writeable:1; UINT8expanddown:1; UINT8code_data:1; UINT8app_system:1; UINT8dpl:2; UINT8present:1; UINT8limit_16_19:4; UINT8unused:1; UINT8always_0:1; UINT8seg_16_32:1; UINT8granularity:1; UINT8base_24_31; }DATA_SEG_DESCRIPTOR*PDATA_SEG_DESCRIPTOR; 共有4种ENTRY格式此处提供的是CODESEGMENT和DATASEGMENT的ENTRY格式.FLAT模式下的ENTRY在base_0_15base_16_23处为0而limit_0_15limit_16_19处为0xfffff.granularity处为
1.表名SEGMENT地址空间是从0到0XFFFFFFFF的4G的地址空间. b从SEGMENT处取出BASEADDRESS和LIMIT.将要访问的ADDRESS首先进行AC__SSCHECK是否超出SEGMENT的限制. c将要访问的ADDRESS+BASEADDRESS形成需要32BIT访问的虚拟地址.该地址被解释成如下格式: typedefstruct { UINT32offset:12; UINT32page_index:10; UINT32pdbr_index:10; }VA*LPVA; dpdbr_index作为CR3的INDEX获得到一个如下定义的数据结构 typedefstruct { UINT8present:1; UINT8writable:1; UINT8supervisor:1; UINT8writethrough:1; UINT8cachedisable:1; UINT8ac__ssed:1; UINT8reserved1:1; UINT8pagesize:1; UINT8ignoreed:1; UINT8__l:3; UINT8ptadr_12_15:4; UINT16ptadr_16_31; }PDE*LPPDE; e从中取出PAGETABLE的地址.并且使用page_index作为INDEX得到如下数据结构 typedefstruct { UINT8present:1; UINT8writable:1; UINT8supervisor:1; UINT8writethrough:1; UINT8cachedisable:1; UINT8ac__ssed:1; UINT8dirty:1; UINT8pta:1; UINT8global:1; UINT8__l:3; UINT8ptadr_12_15:4; UINT16ptadr_16_31; }PTE*LPPTE; f从PTE中获得PAGE的真正物理地址的BASEADDRESS.此BASEADDRESS表名了物理地址的.高20位.加上虚拟地址的offset就是物理地址所在了.
2、ARM系列的MMU ARM出品的CPU,MMU作为一个协处理器存在根据不同的系列有不同搭配需要查询DATASHEET才可知道是否有MMU如果有的话,一定是编号为15的协处理器可以提供32BIT共4G的地址空间 ARMMMU提供的分页机制有1K/4K/64K3种模式.本文介绍的是目前操作系统通常使用的4K模式 涉及的寄存器全部位于协处理器
15. ARM没有SEGMENT的寄存器,是真正的FLAT模式的CPU给定一个ADDRESS,该地址可以被理解为如下数据结构: typedefstruct { UINT32offset:12; UINT32page_index:8; UINT32pdbr_index:12; }VA*LPVA; 从MMU寄存器2中取出BIT14-31,pdbr_index就是这个表的索引,每个入口为4BYTE大小,结构为 typedefstruct { UINT32type:2;//alwayssetto01b UINT32writebackcacheable:1; UINT32writethroughcacheable:1; UINT32ignore:1;//setto1balways UINT32do__in:4; UINT32reserved:1;//set0 UINT32base_addr:22; }PDE*LPPDE; 获得的PDE地址,获得如下结构的ARRAY,用page_index作为索引,取出内容 typedefstruct { UINT32type:2;//alwayssetto11b UINT32ignore:3;//setto100balways UINT32do__in:4; UINT32reserved:3;//set0 UINT32base_addr:20; }PTE*LPPTE; 从PTE中获得的__址和上offset,组成了物理地址. PDE/PTE中其他的BIT,用于访问控制这边讲述的是一切正常,物理地址被正常组合出来的状况 ARM/X86MMU使用上的差异
1、X86始终是有SEGMENT的概念存在.而ARM则没有此概念没有SEGMENTREGISTER..
2、ARM有个DO__IN的概念.用于访问授权.这是X86所没有的概念.当通用OS尝试同时适用于此2者的CPU上一般会抛弃DO__IN的使用.CPU寄存器概述来源wxiu.com__fox时间2009-07-09__
1591.什么是寄存器 所谓寄存器(register),它是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器HYPERLINKhttp://article.wxiu.com/uploads/allimg/090709/
1638300.jpg\t_blankINCLUDEPICTUREhttp://article.wxiu.com/uploads/allimg/090709/
1638300.jpg\*MERGEFORMAT
2.寄存器与CPU指令 在讲CPU的寄存器之前,我们先了解一下CPU指令系统指令系统指的是一个CPU所能够处理的全部指令的__,AthlonXP和P4都是基于x86指令集,这是CPU的根本属性,决定CPU运行什么样的程序 指令一般分为算术逻辑运算指令、浮点运算指令、位操作指令及其他的一些非运算指令,其中整数、地址、指令指针和浮点数据是按照数据形式来划分的通常我们把需要CPU进行不同处理的单个数据称为标量数据ScalaData标量数据既可以是整数数据,也可以是浮点数据其中整数标量数据的存放区一般为通用寄存器GPR,浮点标量数据的存放区一般为浮点寄存器FPR与标量数据相对的是矢量数据VectorData,所谓矢量数据就是指一列需要由处理器作相同处理的数据__比如处理器在做MP3编码的过程中,需要对内存中的音频文件里的各字节数据作相同的MP3编码操作那么通常使用MMX或SSE这类单指令多数据流SIMD指令,将数个字节打包为一组矢量数据,存放在MMX或SSE寄存器中,再送往相应的功能单元进行统一操作 其中通用寄存器是处理器中最快的存储器,用来保存参加运算的操作数和中间结果在通用寄存器的设计上,RISC与CISC(也就是我们常说的x86架构)有着很大的不同CISC的寄存器通常很少——只有8个通用寄存器由于CPU在执行指令过程中,存在指令依赖性,在一定程度上使得x86CPU不能在每个时钟周期中立即发布大量的指令所谓“依赖性”就是指令的执行需要前个指令的运算结果比如程序员经常使用的分支程序,请看下面这个例子 A=C*1 B=A+2 只要变量A的值还不知道,B=A+2就不能进行运算也就是说,只要指令1的结果没有写进寄存器,CPU调度器就不能把指令2发布到执行单元由于程序分支会造成具有较长流水线CPU运行停滞的,目前常用的解决方法是采用分支预测 不过,分支预测同样存在一个问题流水线越长,指令潜伏期也越长,等待前一指令运算结果的时间也越长,同样会造成CPU运行停滞我们知道,程序指令通常都有各类型的条件分支语句,通过验证条件决定执行路线但CPU执行单元内是通过一项特殊的预测机制选择一条路线直接执行(这样可以避免验证语句条件而处于等待情况),然后在后面进行验证如果预测正确则继续往下执行,如果发现以前的预测错误,那么就必须返回原地重新开始,以前的指令就会作废 因此,管线越长,意味着出现分支预测错误的机会就越多,越多在管线内的指令会被清除掉,而且重新让管道填满指令的时间也会越长对于普通处理器来说,如果出现分支预测错误,CPU就不得不将整条流水线清空后从错误的地方重新装满数据、重新执行毫无疑问这将花更多的时间,整体性能就会下降因此,针对通用寄存器少的问题,在x86架构中比较__的解决方法就是增加寄存器的数量和采用“乱序执行”
3.___寄存器不够用 在上面我们已经提到,寄存器只是用来暂时存放指令值的,如果CPU需要把两个值加起来,它需要用1个寄存器来存放运算结果,用2个寄存器来存放相加的数值例如,在以下的方程式中A=2+4 *在寄存器1储存“2”; *在寄存器2储存“4”; *在寄存器3储存“寄存器1+寄存器2”; 因为在微处理器里面有超过3个寄存器,因此这个运算能够轻易地执行,不会造成用光寄存器的情况在这些运算被执行之后,所有的3个数值都能够被保留并重新使用,因此如果我们再想在结果加上2的话,处理器只需要执行寄存器1+寄存器3就可以了如果微处理器仅有2个剩余的寄存器,而我们又需要再次使用2和4的值,那么这些值在覆盖结果A之前,必须储存在主内存之中运算执行的过程则会变成如下所示 *在寄存器1储存“2”; *在寄存器2储存“4”; *在主内存的某个空间储存“寄存器1+寄存器2”; 我们可以看到这里使用了其它的内存访问过程,而在这期间其实还有我们没有提到的其它处理过程,比如主内存的定位也需要占据寄存器,以便让CPU告诉装载/储存单元该往哪里发送数据如果我们需要使用到这些结果的话,那么CPU将不得不首先到主内存中找回这些结果,把目前满载的寄存器驱逐一些数据,把它们写入主内存,然后再把寻找到的数据储存在寄存器里HYPERLINKhttp://article.wxiu.com/uploads/allimg/090709/
1638301.jpg\t_blankINCLUDEPICTUREhttp://article.wxiu.com/uploads/allimg/090709/
1638301.jpg\*MERGEFORMAT这里大家应该能够明白吧,对内存的访问次数将会可怕地增加;你需要访问内存的时间越多,那么处理器等待工作完成的时间就越长——因而造成性能的下降因此面对超标量CPU在并行处理大量运算,x86体系仅有的8个通用寄存器远远不能满足需要,在同一时钟周期中,如果有3个指令发布,你就需要3个输出寄存器和6个输入寄存器我们该怎么办呢?聪明的工程师们发现了突破这个限制的方法“寄存器重命名”
4.寄存器重命名技术 寄存器重命名,是CPU在解码过程中对寄存器进行重命名,解码器把“其它”的寄存器名字变为“通用”的寄存器名字,本质上是通过一个表格把x86寄存器重新映射到其它寄存器,这样可以让实际使用到的寄存器远大于8个这样做的好处除了便于前面指令发生意外或分支预测出错时取消外,还避免了由于两条指令写同一个寄存器时的等待HYPERLINKhttp://article.wxiu.com/uploads/allimg/090709/
1638302.jpg\t_blankINCLUDEPICTUREhttp://article.wxiu.com/uploads/allimg/090709/
1638302.jpg\*MERGEFORMAT 下面我们以一个超标量CPU执行8个算术指令为例假设它在每个时钟周期中能对2个指令解码,引出计算结果是在指令发布后3个时钟周期发生的
(1)在第1个时钟周期,两个指令发布它们互不关联,因此,它们将在3个时钟周期后(第4个时钟周期)引出;
(2)在第2个时钟周期,我们首次遇到了“指令依赖”,指令3需要指令2的结果,此时指令3不能开始发布;
(3)如果是按序执行,指令
4、
5、6就不能在指令3前发布只有在第5个时钟周期时(指令2的结果已得到)才能发布指令3;
(4)在第6个时钟周期有个大问题我们想把结果写到寄存器R1,但这将改变指令5的结果因此,我们只有在R1空闲时(第10个时钟周期)才能发布指令6 按照正常情况处理的话,尽管这个CPU每个时钟周期可以对2个指令解码,但它每个时钟周期的指令执行数只有
0.53如果每次程序所需的寄存器正被使用,我们可以把数据放到其它的寄存器中,在第6个时钟周期将寄存器R1重命名,指令6和指令8不再耽误CPU的工作结果是我们能够将每个时钟周期的指令执行数提高50%寄存器重命名技术可以使x86CPU的寄存器可以突破8个的限制,达到32个甚至更多寄存器重命名技术现在已经深深地扎根于超标量CPU中了
5.乱序执行技术 除此之外,处理器工程师还引入了乱序执行技术,从一定程度上来缓解通用寄存器不足的问题采用乱序执行技术的目的是为了使CPU内部电路满负荷运转并相应提高了CPU运行程序的速度 这好比请A、B、C三个名人为春节联欢晚会题写横幅“春节联欢晚会”六个大字,每人各写两个字,如果这时在一张大纸上按顺序由A写好“春节”后再交给B写“联欢”,然后再由C写“晚会”,那么这样在A写的时候,B和C必须等待,而在B写的时候C仍然要等待而A已经没事了但如果采用三个人分别用三张纸同时写的做法,那么B和C都不必等待就可以同时各写各的了,甚至C和B还可以比A先写好也没关系(就像乱序执行),但当他们都写完后就必须重新在横幅上按“春节联欢晚会”的顺序排好(自然可以由别人做,就象CPU中乱序执行后的重新排列单元)才能挂出去 不过,虽然采用寄存器重命名技术、乱序执行技术,但仍不能从根本上解决x86处理器通用寄存器不足的问题以寄存器重命名技术来说,这种技术的寄存器操作相对于RISC来说,要花费一个时钟周期来对寄存器进行重命名,这无形中降低了处理器性能以及流水线工作效率,也增加了程序和编译器的优化难度针对这个问题,最新的x86-64架构中(K8处理器),AMD在x86架构基础上将通用寄存器和SIMD寄存器的数量增加了1倍其中新增了8个通用寄存器以及8个SIMD寄存器作为原有x86处理器寄存器的扩充 这些通用寄存器都工作在64位模式下,经过64位编码的程序就可以使用到它们这些64位寄存器称为RAX、RBX、RCX、RDX、RDI、RSI、RBP、RSP、RIP以及EFLAGS,在32位环境下并不完全使用到这些寄存器,同时AMD也将原有的EAX等寄存器扩展至64位的RAX,这样可以增强通用寄存器对字节的操作能力从扩充方式上看,EAX等寄存器可以看做是RAX的一个子集,系统仍然可以完整地执行以往的32位编码程序增加通用寄存器除了可高效存储数据外,还可作为寻址时的地址指针,从而缩短指令长度和指令执行时间,加快CPU的运算处理速度,同时也给编程带来方便 此外,为了保证K8的分支预测更有效率,K8的分支预测寄存器增加到64个分支指令可以被设为真或假,而每个指令中的6位被分配到单独一个预测寄存器中,只有预测寄存器被设定为“真”时那些指向预测寄存器为“真”的指令结果才会被执行其次由于所有的分支都能并行执行,CPU所花的时间同只执行单个分支的时间是相同的,降低了预测出错的风险第三由于CPU不再跳跃执行,它不会把程序代码分成小块也就是说,稍前和稍后的程序代码可以打包这样CPU能够一并将它们发布,增大并行工作量从而使性能提高10%~15%,特别是在整数代码部分 不过在x86-64中,寄存器的扩展部分似乎仅对于整数、地址数据有效对浮点和向量数据则仍然保持原样我们能从K8向64位的扩展所获得的好处,只不过是可以在同样一条指令中,处理更大数值的整数数值以及管理空间更大的内存区域而已而在32位的情况下,由于通用寄存器只能容纳最大32位的数据,因此显然要花费更多条指令对尺寸超过32位的数据进行处理这种改进对服务器、科学计算这样的领域具有一定的意义,但显然并不是普通家用环境急需的改进 可以说,处理器的寄存器对处理器的性能有着巨大的影响但是无论怎么发展,通用型CPU目前还没有脱离x86架构的限制,也许有一天,新的寄存器技术能让我们的CPU变得更加功能强大!。