保护模式--基础

来源:互联网 发布:软件wbs 编辑:程序博客网 时间:2024/06/14 07:52
1.IA32下,CPU有两种工作模式:实模式和保护模式;
2.打开PC后,开始时CPU是工作在实模式下的,经过某种机制后,才能进入保护模式;
3.保护模式下,CPU有着巨大的寻址能力,为强大的32位操作系统提供更好的硬件保障;
4.8086是16位CPU,16位寄存器,16位数据总线,20位地址总线和1M的寻址能力;
  物理地址=段值*16+偏移,段值和偏移都是16位
5.80386 CPU 32位,32地址总线,寻址空间为4G,单从寻址方面讲,使用16位寄存器的方法已经不够用了,  所以需要新的方法来提供更强大的寻址能力;
6.在实模式下,段值可以看做是地址的一部分,段值位xxxxh表示以xxxx0h开始的一段内存  在保护模式下,段值仅仅变成了一个索引,这个索引指向一个数据结构的一个表项,表项中详细定义了段的启示地址、  界限、属性等内容。这个数据结构就叫GDT,表项就叫描述符;
7.GDT的作用是用来提供段式存储机制,这个机制是通过段寄存器和GDT中的描述符共同提供。
8.描述符的种类:代码段,数据段,系统段,门;
9.8086只有20位地址总线,只能寻址1M,若访问超过1M的地址,系统会回卷回去,重新从地址零开始寻址;  80286时系统可以访问1M以上的内存了,且不会再回卷寻址,这样就造成了不兼容  为了保证兼容,IBM使用8042键盘控制器来控制第20个(从零开始数)地址位,即A20地址线,如果不打开,第20个地址将会总是0;
10.CR0的第0位置,PE位为实模式和保护模式的关键,为0时,CPU运行在实模式,为1时,运行与保护模式; 
11.进入保护模式的主要步骤:1).准备GDT2).用lgdt加载gdtr3).打开A204).置CR0的第0位PE位5).跳转,进入保护模式
12.从保护模式回到实模式,需要加载一个合适的描述符选择子到有关寄存器,以使对应段描述符高速缓冲寄存器中含有   合适的段界限和属性。而且,不能直接从32位代码段返回实模式,只能从16位代码段中返回。这是因为无法实现从   32位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)。
  13.LDT也是一种描述表,月GDT类似,只不过选择子的TI位必须置1,在运行时,需要先用lldt指令加载ldtr,lldt的操作   数是GDT中用来描述LDT的描述符。
  14.可以在LDT中增加更多的段,比如数据段,堆栈段等,这样可以把一个单独的任务所用到的所有东西封装在一个LDT中,   这种思想是多任务处理的一个雏形。
15.增加一个用LDT描述的任务:   1).增加一个32位的代码段,内容尽量简单;   2).增加一个段,内容是一个描述符表(LDT),可以只有一个代码段描述符,也可以添加更多的描述符描述更多的段。      注意,涉及的选择子的TI位是1.   3).在GDT中增加一个描述符,用以描述这个LDT,同时要定义其描述符。   4).增加新添的描述符的初始化代码,主要是针对段基址。   5).用新加的LDT描述的局部任务准备完毕。   6).使用前用lldt指令加载ldtr,用jmp指令跳转等方式运行。
   16.描述符中段基址和段界限定义了一个段的范围,对超越段界限之外的地址的访问时被禁止的,这是对段的一种保护;段属性作为对一个段各个方面的定义规定和限制了段的行为和性质,从功能上来讲,这仍然是一种保护。
17.特权级,较为核心的代码和数据,被放在特权级较高的层级中。处理器用特权级这样的机制来避免低特权级的任务在不被允许的情况下访问位于高特权级的段。如果处理器检测到一个访问请求不合法,将会产生常规保护错误。
18.CPL 当前执行的程序或任务的特权级。被存储在cs和ss的第0位和第一位上。通常,CPL等于代码所在的段的特权级当程序转移到不同特权级的代码段时,处理器将改变CPL。一致代码段可以被相同或者更低特权级的代码访问。当处理器访问一个与CPL特权级不同的一致代码段时,CPL不会被改变。
19.DPL表示段或者门的特权级。存储在段描述符或者门描述符的DPL字段中。当当前代码段试图访问一个段或者门时,DPL将会和CPL以及段或门选择子的RPL相比较,根据段或者门的类型的不同,DPL将会区别对待。
20.RPL通过段选择子的第0位和第一位表现出来。处理器通过检查RPL和CPL来确认一个访问请求是否合法。即便提出访问请求的段有足够的特权级,如果RPL不够也是不行的。
21.程序从一个代码段转移到另一个代码段之前,目标代码段的选择子会被加载到cs中。作为加载过程的一部分,处理器   将会检查描述符的界限、类型、特权级等内容。如果检验成功,cs将被加载,程序控制将转移到新的代码段中,从eip   指示的位置开始执行。
22.序控制转移的发生,可以由jmp,call,ret,sysenter,sysexit,int n或iret 引起,也可以由中断和异常机制引起。
23.使用jmp或call指令可以实现4中转移:1.目标操作数包含目标代码段的段选择子。(通过jmp和call直接转移)2.目标操作数指向一个包含目标代码段选择子的调用门描述符。(通过某个描述符的间接转移)3.目标操作数指向一个包含目标代码段选择子的TSS。(通过某个描述符的间接转移)4.目标操作数指向一个任务门,这个任务门指向一个包含目标代码段选择子的TSS。(通过某个描述符的间接转移)
24.通过jmp和call能进行的代码段间转移是非常有限的,对于非一致代码段,只能在相同特权级代码段之间转移。遇到一致代码段也最多能从低到高,而且CPL不会改变。如果想自由地进行不同特权级之间的转移需要运用门描述符或者TSS。
25.门也是一种描述符,主要定义了目标代码对应段的选择子、入口地址的偏移和一些属性。
27.门描述符分为4种:调用门,中断门,陷阱门,任务门;中断门和陷阱门时特殊的调用门。
28.调用门本质上只不过是个入口地址,只是增加了若干的属性而已。可实现不同特权级的代码之间的转移。
29.使用调用门进行不同特权级代码之间的转移,检验规则为:   假设 代码A 转移到 代码B,用一个调用门G,调用门中的目标选择子指向代码B的段;   涉及的特权级:CPL,RPL,DPL_B(代码B的DPL),DPL_G(调用门G的DPL);   一致/非一致代码段都要求:CPL<=DPL_G,RPL<=DPL_G;   还要求,使用call指令时: 一致/非一致代码段 DPL_B<=CPL   使用jmp指令时:一致代码段要求 DPL_B<=CPL;非一致代码要求 DPL_B=CPL;   即通过调用门和call指令,可以实现从低特权级到高特权级的转移,无论目标代码段是一致的还是非一致的。   调用门只能实现特权级由低到高的转移。     特权级变换的的转移要有严格的特权级检验,变化的时候堆栈也要发生变化。处理器的这种机制避免了高特权级   的过程由于栈空间不足而崩溃。   30.如果一个调用或者跳转指令在段间而不是在段内进行的,称之为长跳转,反之如果在段内则称为短跳转。   31.jmp长短跳转只是结果不同;call指令长短调用会对堆栈的影响是不同的。call指令短调用,call指令执行时下一条指令的eip压栈,到ret指令执行时,这个eip被从堆栈中弹出。call指令长调用,返回的时候跟调用的一样也是长转移,所以返回的时候也需要调用者的cs,于是call指令执行时被压栈的就不仅仅有eip,还有cs。32.call一个调用门也是一个长调用,但是call指令执行前后的堆栈发生了切换。Intel提供了一种机制,堆栈发生切换   时会将堆栈A的诸多内容复制到堆栈B中。   33.事实上,每一个任务最多都可能在4个特权级剑转移,所以,妹儿任务实际上需要4个堆栈。
34.当堆栈发生切换时,从TSS中获取堆栈对应的ss和esp;
35.TSS,(Task-State Stack)是一个数据结构,里面包含多个字段,3个ss和3个esp对应偏移4到偏移27的3个字段。   由于只是在由外层到内层(低特权级到高特权级)切换时新堆栈才会从TSS中取得,所以TSS中没有位于最外层的ring3   的堆栈信息。使用的时候需要手动按TSS的结构来创建添加并初始化。   36.转移过程,CPU在整个过程中所做的工作:   1.根据目标代码段的DPL(新的CPL)从TSS中选择对应该切换至哪个ss和esp;   2.从TSS中读取新的ss和esp。过程中如果发现ss、esp或者TSS界限错误都会导致无效TSS异常(#TS);   3.对ss描述符进行检验,如果发生错误,同样产生#TS异常;   4.暂时性地保存当前ss和esp的值;   5.加载新的ss和esp;   6.将刚刚保存起来的ss和esp的值压入新栈;   7.从调用者堆栈中将参数复制到被调用者堆栈(新堆栈)中,复制参数的数目由调用门中Param Count一项来决定,     如果Param Count是零的话,将不会复制参数。   8.将当前的cs和eip压栈。   9.加载调用门中指定的新的cs和eip,开始执行被调用者过程。
37.调用门中的Param Count只有5位,最多只能复制31个参数;如果参数超过31个,可以让其中的某个参数变成   指向一个数据结构的指针,或者通过保存在新堆栈里的ss和esp来访问旧堆栈中的参数。ret基本上市call的   反过程,只是带参数的ret指令会同事释放事先被压栈的参数。   38.ret指令可以实现短返回长返回,也可以实现带有特权级变换的长返回,   由被调用者到调用者的返回过程中,处理器的工作包含以下几步:   1.检查保存的cs中的RPL以判断返回时时否要变换特权级。   2.加载被调用者堆栈上的cs和eip(此时会进行代码段描述符和选择子类型和特权级检验)   3.如果ret指令含有参数,则增加esp的值以跳过参数,然后esp将指向被保存过的调用者ss和esp。     注意,ret的参数必须对应调用门中的Param Count的值。   4.加载ss和esp,切换到调用者堆栈,被调用者的ss和esp被丢弃。在这里将会进行ss描述符、esp以及ss段描述符检验。   5.如果ret指令含有参数,增加esp的值以跳过参数(此时已经在调用者堆栈中)。   6.检查ds,es,fs,gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不适用于一致代码段),那么一个空     描述符会被加载到该寄存器。 
39.使用调用门的过程实际上分为两个部分,一部分是从低特权级到高特权级,通过调用门和call指令来实现;
   另一部分则是从高特权级到低特权级,通过ret指令来实现。
0 0