New Microsoft Word Document.docx_第1页
New Microsoft Word Document.docx_第2页
New Microsoft Word Document.docx_第3页
New Microsoft Word Document.docx_第4页
New Microsoft Word Document.docx_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

8086保护模式相关知识保护模式,是一种80286系列和之后的x86兼容CPU操作模式。保护模式有一些新的特色,设计用来增强多工和系统稳定度,像是 内存保护,分页系统,以及硬件支援的 虚拟内存。大部分的现今 x86操作系统都在保护模式下运行,包含 Linux、FreeBSD、以及微软Windows 2.0 和之后版本。另外一种286和其之后CPU的运行模式是实模式,一种向前兼容且关闭了保护模式这些特性的CPU运行模式。用来让新的芯片可以运行旧的软件。依照设计的规格,所有的x86 CPU都是在实模式下开机,来确保传统操作系统的向前兼容性。在任何保护模式的特性可用前,他们必须要由某些程序手动地切换到保护模式。在现今的计算机,这种切换通常是由操作系统在开机时候必须完成的第一件任务的一个。它也可能当CPU在保护模式下运行时,使用虚拟86模式来运行设计运行在实模式下的代码。保护模式与实模式相对应。在80286以前,CPU只有实时模式,地址总线有20位,而内存地址是16位,也就是最多能够访问220=1M的内存空间。在80286及以后,内存地址改为16位或32位,至少可以访问到232=4G的内存空间。但为了保证后续的CPU能够运行旧的CPU,只能保持向下兼容。因此,80286及以后的CPU首先进入实模式,然后通过切换机制再进入到保护模式。实模式那么什么是实模式呢?CPU复位(reset)或加电(power on)的时候以实模式启动,处理器以实模式工作。在实模式下,内存寻址方式和8086相同,由16位段寄存器的内容乘以16(10H)当做段基地址,加上16位偏移地址形成20位的物理地址,最大寻址空间1MB,最大分段64KB。可以使用32位指令。32位的x86 CPU用做高速的8086。在实模式下,所有的段都是可以读、写和可执行的。2保护模式与实模式相比,主要是两个差别:一是提供了段间的保护机制,防止程序间胡乱访问地址带来的问题,二是访问的内存空间变大,见前面的描述。在8086/8088时代,处理器只存在一种操作模式(Operation Mode),当时由于不存在其它操作模式,因此这种模式也没有被命名。自从80286到80386开始,处理器增加了另外两种操作模式保护模式和系统管理模式SMM(System Management Mode),因此,8086/8088的模式被命名为实地址模式RM(Real-address Mode)。保护模式是处理器的本机模式,在这种模式下,处理器支持所有的指令和所有的体系结构特性,提供最高的性能和兼容性。对于所有的新型应用程序和操作系统来说,建议都使用这种模式。为了保证PM的兼容性,处理器允许在受保护的,多任务的环境下执行RM程序。这个特性被称做虚拟8086模式(Virtual -8086 Mode),尽管它并不是一个真正的处理器模式。Virtual-8086模式实际上是一个PM的属性,任何任务都可以使用它。RM提供了Intel 8086处理器的编程环境,另外有一些扩展(比如切换到PM或SMM的能力)。当主机被Power-up或Reset后,处理器处于RM下。SMM是一个对所有Intel处理器都统一的标准体系结构特性。出现于Intel386 SL芯片。这个模式为OS实现平台指定的功能(比如电源管理或系统安全)提供了一种透明的机制。当外部的SMM interrupt pin(SMI#)被激活或者从APIC(Advanced Programming Interrupt Controller)收到一个SMI,处理器将进入SMM。在SMM下,当保存当前正在运行程序的整个上下文(Context)时,处理器切换到一个分离的地址空间。然后SMM指定的代码或许被透明的执行。当从SMM返回时,处理器将回到被系统管理中断之前的状态。由于机器在Power-up或Reset之后,处理器处于RM状态,而对于Intel 80386以及其后的芯片,只有使用PM才能发挥出最大的作用。所以我们就面临着一个从RM切换到PM的问题。全局描述表(GDT Global Descriptor Table):在保护模式下,一个重要的必不可少的数据结构就是它。为什么要有GDT?我们首先考虑一下在实时模式下的编程模型:在实时模式下,我们对一个内存地址的访问是通过Segment:Offset的方式来进行的,其中Segment是一个段的Base Address,一个Segment的最大长度是64 KB,这是16-bit系统所能表示的最大长度。而Offset则是相对于此Segment Base Address的偏移量。Base Address+Offset就是一个内存绝对地址。由此,我们可以看出,一个段具备两个因素:Base Address和Limit(段的最大长度),而对一个内存地址的访问,则是需要指出:使用哪个段?以及相对于这个段Base Address的Offset,这个Offset应该小于此段的Limit。当然对于16-bit系统,Limit不要指定,默认为最大长度64KB,而 16-bit的Offset也永远不可能大于此Limit。我们在实际编程的时候,使用16-bit段寄存器CS(Code Segment),DS(Data Segment),SS(Stack Segment)来指定Segment,CPU将段寄存器中的数值向左偏移4-bit,放到20-bit的地址线上就成为20-bit的Base Address。到了保护模式,内存的管理模式分为两种,段模式和页模式,其中页模式也是基于段模式的。也就是说,保护模式的内存管理模式事实上是:纯段模式和段页式。进一步说,段模式是必不可少的,而页模式则是可选的如果使用页模式,则是段页式;否则这是纯段模式。既然是这样,我们就先不去考虑页模式。对于段模式来讲,访问一个内存地址仍然使用Segment:Offset的方式,这是很自然的。由于保护模式运行在32位系统上,那么Segment的两个因素:Base Address和Limit也都是32位的。IA-32允许将一个段的Base Address设为32-bit所能表示的任何值(Limit则可以被设为32-bit所能表示的,以212为倍数的任何值),而不象实时模式下,一个段的Base Address只能是16的倍数(因为其低4-bit是通过左移运算得来的,只能为0,从而达到使用16-bit段寄存器表示20-bit Base Address的目的),而一个段的Limit只能为固定值64 KB。另外,保护模式,顾名思义,又为段模式提供了保护机制,也就说一个段的描述符需要规定对自身的访问权限(Access)。所以,在保护模式下,对一个段的描述则包括3方面因素:Base Address, Limit, Access,它们加在一起被放在一个64-bit长的数据结构中,被称为段描述符。这种情况下,如果我们直接通过一个64-bit段描述符来引用一个段的时候,就必须使用一个64-bit长的段寄存器装入这个段描述符。但Intel为了保持向后兼容,将段寄存器仍然规定为16-bit(尽管每个段寄存器事实上有一个64-bit长的不可见部分,但对于程序员来说,段寄存器就是16-bit的),那么很明显,我们无法通过16-bit长度的段寄存器来直接引用64-bit的段描述符。怎么办?解决的方法就是把这些长度为64-bit的段描述符放入一个数组中,而将段寄存器中的值作为下标索引来间接引用(事实上,是将段寄存器中的高13-bit的内容作为索引)。这个全局的数组就是GDT。事实上,在GDT中存放的不仅仅是段描述符,还有其它描述符,它们都是64-bit长,我们随后再讨论。GDT可以被放在内存的任何位置,那么当程序员通过段寄存器来引用一个段描述符时,CPU必须知道GDT的入口,也就是基地址放在哪里,所以Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDT是保护模式所必须的数据结构,也是唯一的不应该,也不可能有多个。另外,正象它的名字(Global Descriptor Table)所揭示的,它是全局可见的,对任何一个任务而言都是这样。GDT是保护模式所必须的数据结构,那么我们在进入保护模式之前,必须设定好GDT,并通过LGDT将其装入相应的寄存器。尽管GDT允许被放在内存的任何位置,但由于GDT中的元素描述符都是64-bit长,也就是说都是8个字节,所以为了让CPU对GDT的访问速度达到最快,我们应该将GDT的入口地址放在以8个字节对齐,也就是说是8的倍数的地址位置。GDT中第一个描述符必须是一个空描述符,也就是它的内容应该全部为0。如果引用这个描述符进行内存访问,则是产生General Protection异常。如果一个OS不使用虚拟内存,段模式会是一个不错的选择。但现代OS没有不使用虚拟内存的,而实现虚拟内存的比较方便和有效的内存管理方式是页式管理。但是在IA-32上如果我们想使用页式管理,我们只能使用段页式没有方法可以完全禁止段模式。但我们可以尽力让段的效果降低的最小。IA-32提供了一种被称作“Basic Flat Model”的分段模式可以达到这种效果。这种模式要求在GDT中至少要定义两个段描述符,一个用来引用Data Segment,另一个用来引用Code Segment。这2个Segment都包含整个线性空间,即Segment Limit = 4 GB,即使实际的物理内存远没有那么多,但这个空间定义是为了将来由页式管理来实现虚拟内存。在这里,我们只是处于启动阶段,所以我们只需要初步设置一下GDT,等真正进入保护模式,启动了OS Kernel之后,具体OS打算如何设置GDT,使用何种内存管理模式,由Kernel自身来设置,启动只需要给Kernel的数据段和代码段设置全部线性空间就可以了。段描述符的格式如下图所示:具体到代码段和数据段,它们的格式如下图所示:下面就是在启动阶段为进入保护模式而设置的临时的gdt。这里定义了3个段描述符:第一个是系统规定的空描述符,第2个是引用4 GB线性空间的代码段,第3个是引用4 GB线性空间的数据段。这是Basic Flat Model所要求的最下GDT设置,但就启动阶段,只是为了进入保护模式,并为内核提供一个连续的,最大的线性空间这个目的而言,已经足够了。# Descriptor tablesgdt:.word 0, 0, 0, 0 # dummy.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb).word 0 # base address = 0.word 0x9A00 # code read/exec.word 0x00CF # granularity = 4096, 386# (+5th nibble of limit).word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb).word 0 # base address = 0.word 0x9200 # data read/write.word 0x00CF # granularity = 4096, 386# (+5th nibble of limit)设置好GDT之后,我们需要通过LGDT指令将设定的gdt的入口地址和gdt表的大小装入GDTR寄存器。GDTR寄存器包括两部分:32-bit的线性基地址,以及16-bit的GDT大小(以字节为单位)。需要注意的是,对于32-bit线性基地址,必须是32-bit绝对物理地址,而不是相对于某个段的偏移量。而我们在启动阶段,在进入保护模式之前,我们CS和DS设置很可能不是0,所以我们必须计算出gdt的绝对物理地址。为了执行LGDT指令,你需要把这两部分内容放在内存的某个位置,然后将这个位置的内存地址作为操作数传递给LGDT指令。然后LGDT指令会自动将保存在这个位置的这两部分值装入GDTR寄存器。# 这是存放GDTR所需的两部分内容的位置gdt_48:.word 0x8000 # gdt limit=2048,# 256 GDT entries.word 0, 0 # gdt base (filled in later)# 下面这段代码用来计算GDT的32-bit线性地址,并将其装入GDTR寄存器。xorl %eax, %eax # Compute gdt_basemovw %ds, %ax # (Convert %ds:gdt to a linear ptr)shll 4, %eaxaddl $gdt, %eaxmovl %eax, (gdt_48+2)lgdt gdt_48 # load gdt with whatever is appropriate在进入保护模式之前,除了需要设置和装入GDT之外,还需要做如下一些事情:屏蔽所有可屏蔽中断;装入IDTR;中文全称:中断描述表寄存器所有协处理器被正确的复位。由于在实时模式和保护模式下的中断处理机制有一些不同,所以在进入保护模式之前,务必禁止所有可屏蔽中断,这可以通过下面两种方法之一:使用CLI指令;对8259A可编程中断控制器编程以屏蔽所有中断。即使当我们进入保护模式之后,也不能马上将中断打开,这时因为我们必须在OS Kernel中对相关的保护模式中断处理所需的数据结构正确的初始化之后,才能打开中断,否则会产生处理器异常。在实时模式下,中断处理使用IVT(Interrupt Vector Table),在保护模式下,中断处理使用IDT(Interrupt Descriptor Table),所以,我们必须在进保护模式之前设置IDTR。IDTR的格式和GDTR相同,IDTR的装入方式和GDTR也相同。由于IDT中相关的中断处理程序需要让OS Kernel来设定,所以在启动阶段,我们只需要将IDTR中IDT的基地址和Size都设为0就可以了,随后,等进入保护模式之后,由OS Kernel来真正设置它。关于中断机制和中断处理,请参考 Interrupt & Exception ,这里不再赘述。# 这是存放IDTR所需的两部分内容的位置#idt_48:.word 0 # idt limit = 0.word 0, 0 # idt base = 0L# 对于IDTR的处理,只需要这一条指令即可lidt idt_48 # load idt with 0,0# 通过设置8259A PIC,屏蔽所有可屏蔽中断#movb xFF, %al # mask all interrupts for nowoutb %al, x

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论