您的位置:首页 > 其它

《自己动手做操作系统》保护模式阅读报告

2013-05-02 17:24 260 查看
一、 基本

1、实模式下的寻址模式和寻址能力:

寻址模式为 段值*16+偏移值 ,寻址能力为0~FFFFFh。

当时由于计算机的发展,地址线增加到了20位,但是处理器仍是16位的,由于16位的寄存器不能存放20位的地址,因此内存被分成多个64KB的段,段值如00000、10000、20000等,由于最后一个十六进制数都为0,因此省略了,将高16位存放在段寄存器,偏移值的也是16位的,对每一个段都可以找0~FFFF的偏移。由此实现了20位的寻址。

2、实模式下段寄存器的作用:

结合1可知,段寄存器可以帮助16位的寄存器实现20位的寻址。

另外,段寄存器的存在也方便了编写代码,代码中的label标识的都是相对于cs指示的基址的偏移,这样无论程序被加载到什么位置,都不影响数据的引用和指令的跳转,如果没有段寄存器,而是直接使用物理地址,那就没有这种灵活性了。

3、保护模式的寻址模式:

保护模式的地址转换的过程是:逻辑地址→线性地址→物理地址。

(1)逻辑地址到线性地址的转换。

段寄存器中保存了段选择子,段选择子中有相对于GDT或LDT的基址的偏移。具体是GDT还是LDT是由段选择子中的TI位决定的,TI=0 描述符在GDT中,TI=1 描述符在LDT中。

GDT或LDT中存有段描述符,描述符中有段基址和段界限及其它属性。

GDTR寄存器中存有GDT的基址(这个地址是线性地址)。

具体的转换过程如下:

首先通过GDTR找到GDT的基址(如果开启了分页机制,GDTR中的线性地址是需要先通过分页机制转换到物理地址的);然后通过段寄存器中的段选择子所存的偏移找到该段的描述符;取出该描述符中的段基址,然后加上逻辑地址就得到线性地址了。

(2)线性地址到物理地址的转换。

CR3寄存器中存有页目录基址及一些属性。显然,该寄存器中存的地址是物理地址,如果这个地址是线性地址的话,就发生死循环了。

页表分为两级,页目录表和页表。其中页目录表只有1个。所有的表都是4KB的大小,有1024个表项。页目录表中的每个表项对应了一个页表的基址,而页表中的每个表项对应了一个物理页的基址。

具体的转换过程如下:

首先通过CR3找到页目录表的基址,线性地址的高10位是要找的页目录表项的偏移;该页目录表项指向一个页表的基址,线性地址的中间10位是要找的页表表项的偏移;该页表表项指向一个物理页的基址,然后低12位与该物理页基址相加即是最后的物理地址。

之所以线性地址要拆成这三个结构很简单,每页有1024个表项,自然需要10位来表示所有可能的偏移了。最后物理页的大小为4K,需要12位表示偏移量。10+10+12 = 32位,这就是线性地址的构成。

4、GDT和LDT:

关于GDT和LDT在3中已经做了介绍,这部分是关于它们在保护模式中寻址的作用。

另外GDT和LDT还有一个作用就是提供保护。GDT和LDT的属性中有DA_DPL0到DA_DPL3这几个特权级属性,另外还有DA_DR、DA_C等描述代码和数据段的属性,这些结合使用可以实现对访问的控制,以提供保护的功能。保护模式中我们之所以能做一些像建立分页机制这类很底层的动作,是因为在没指定特权级属性时,这两位是00,而0特权级是最高的特权级。

二、 扩展

关于对保护模式的认识,查询了很多资料,进行过很多总结,对每一行代码都进行了仔细的研读。下面是一些比较难理解的代码的笔记:

1、关于切换到保护模式的代码:

; 准备切换到保护模式

mov eax,cr0

or eax,1

mov cr0,eax

; 真正进入保护模式

jmp dword SelectorCode32:0 ;

这段代码仔细一想会觉得有问题,前三句开启了保护模式,也就是说执行完前三句后原先cs中的值的意义发生了变化,由基址变成了选择子,但是其中的值是没有变的,那么它为什么能继续执行后面的jmp这条指令呢,按理来说应该不知道跑飞到哪去了。

原因是这个:

只有在cs值刷新后,保护机制才正式开始。

2、关于GDTR中存放的地址是线性地址还是物理地址的问题:

网上说分页机制开启后,除cr3中基址外,所有的地址都要通过分页机制进行转换,也就是说会出现这样一种情况:

开启分页机制以后,GDTR中的地址值是没有发生改变的,但该地址的实际意义已经发生变化,原先由于分页机制没有开启是直接寻址的,现在分页机制已经开启,这也就意味着现在该地址需要被通过cr3指向的页目录表及相应的页表转换成物理地址进行定位。

我猜测,为了在开启分页机制后仍能使用的GDT,建立的页表机制必须保证GDT基址被映射到相同的物理地址处。如果不是这样的话,GDTR将找不到GDT,这会造成保护模式寻址的失败。

3、调用门存在的意义是什么:

调用门存在的意义是它可以进行特权级的跃迁,只要当前代码段的CPL、RPL小于DPL_G(即当前特权级高于调用门的特权级),就可以通过调用门访问到由调用门指向的,比当前代码段特权级更高的代码段(call指令时目标代码的DPL<=当前代码段的CPL;jmp指令时目标代码的DPL=当前代码的CPL)。

显然,call实现了特权级跃迁。

4、调用门返回的最后一步是什么意思:

调用门返回的第6步是检查ds、es、fs及gs段寄存器的内容,如果其中一个寄存器包含的选择符是一个段选择符,并且其DPL值小于CPL,那么,清相应的段寄存器。

控制单元这么做是为了禁止用户态的程序利用内核以前所用的段寄存器。如果不清这些寄存器,怀有恶意的用户态程序就可能利用它们来访问内核地址空间。

5、为什么实模式所用的符号和保护模式所用的符号要分开声明:

[SECTION.data1] ; 数据段

ALIGN 32

[BITS 32]

LABEL_DATA:

; 实模式下使用这些符号

; 字符串

_szPMMessage: db "In Protect Mode now. ^-^", 0Ah, 0Ah, 0 ;

.. . . . .

; 保护模式下使用这些符号

szPMMessage equ _szPMMessage - $$

.. . . . .

; END of [SECTION .data1



这是因为实模式下使用符号的偏移是相对于ds的基址来说的,而ds在一开始被赋为cs的值,_szPMMessage指示的正是这个偏移。

而保护模式下,ds段的选择子指向的段描述符的基址是LABEL_DATA,因此这里使用的偏移是相对于该段的偏移,即 _szPMMessage - $$ , $$即是段首。

6、关于中断那一节的ICW2的构造和写入:

ICW2 是中断类型码的初始化命令字,对于全部的IRQ高5位都是相同的,也因此被称为base address。举个例子,比如说base address是01001(B)=9(D),那么当ICW2 的值是01001001(B)的时候,它所代表的中断向量号就是9+1=10,这时就产生了IRQ 10的中断。这种“寻址”的方式和其他的方式一样,[2:0]是偏移。

ICW2写入的是高5位,低3位由系统填充。



7、关于pmtest9.asm源码注掉jmp $不能返回dos的问题:

如果你试一下pmtest9.asm,会发现直接注释掉jmp $ 是无法返回dos的,实模式下是没有分页机制的,需要在LABEL_SEG_CODE16标注的那段代码中将分页机制关掉:



;16 位代码段. 由 32 位代码段跳入, 跳出后到实模式

[SECTION.s16code]

ALIGN 32

[BITS 16]

LABEL_SEG_CODE16:

; 跳回实模式:

mov ax,SelectorNormal

mov ds,ax

mov es,ax

mov fs,ax

mov gs,ax

mov ss,ax



mov eax, cr0

and al, 11111110b

mov cr0, eax



LABEL_GO_BACK_TO_REAL:

jmp 0:LABEL_REAL_ENTRY



Code16Len equ $ -LABEL_SEG_CODE1



可以在红色代码下面加一句and eax,7FFFFFFFh,关掉分页机制。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: