您的位置:首页 > 其它

《一个操作系统的实现》(三):1.认识保护模式

2013-05-07 17:36 288 查看
进入第三章的学习~第三章开始每章内容变多了,所以以后每学习一节写一篇文章~

顺便注一句:书上“用来生成描述符的宏”只是节自光盘中的pm.inc文件的,我照书上敲了那短短一段发现编译的时候报错- -不过我相信大家的眼睛都比我雪亮

因为引导扇区空间只有512个字节,解决这个问题有俩办法:自己写一个引导扇区or借用别人的引导扇区(从作者的话看起来以后会涉及自己写引导扇区~期待),咱用第二种,借用一下别人的扇区。又要去Bochs官网下东西了(还是进不去。。),幸亏有好心人~freedos-img下载,把其中的a.img复制到目录中,改名为freedos.img。用第二章的方法再生成一个叫做pm.img的软盘映像(bximage命令,然后fd
-> 1.44 -> pm.img),也放到目录中。然后修改bochsrc文件,把原先的floppy:…与boot: …删掉,换成下面三行:

floppya: 1_44=freedos.img, status=inserted

floppyb: 1_44=pm.img, status=inserted

boot: a

启动Bochs,会发现界面显示出A:\>,这时我们输入format b:,会提示Format operation complete.(这时不用关Bochs)

在pmtest1.asm中将org后面的07c00h改为0100h,重新编译(注意,这里编译成.com):

nasm pmtest1.asm -o pmtest1.com

将pmtest1.com复制到虚拟软盘pm.img上:

sudo mount -o loop pm.img /mnt/floppy(如果没有此目录,则要先mkdir /mnt/floppy,不然会报“挂载点/mnt/floppy不存在”)

sudo cp pmtest1.com /mnt/floppy/

sudo umount /mnt/floppy

如果成功的话,在Bochs中输入dir b:会出现Directory of B:\*.*,下面还有几行,如果不成功,会出现File not found.这说明pmtest1.com复制失败(有可能是因为关了Bochs)

然后在Bochs中执行b:\pmtest1.com,会发现红色的P出现在了屏幕最右端~

以上为代码操作部分,下面是理论部分——

“Intel 8086是16位的CPU,有16位的寄存器、16位数据总线、20位地址总线,1MB寻址能力。”

物理地址 = 段值 * 16 + 偏移 (其中段值和偏移均为16位)

实模式和保护模式中的段的概念有着根本区别。实模式下,段值可看作是地址的一部分(比如说段值为XXXXh表示以XXXX0h开始的一段内存)。但是保护模式下,段只是一个索引,指向GDT(即global descriptor table,全局描述符表)的一个表项(描述符)。描述符详细定义了段的起始地址、界限、属性等内容。GDT的作用是提供段式存储机制(此机制通过段寄存器和GDT中的描述符共同提供)

一个讲GDT描述符的文章见这里(其中涉及到“一致码段”,下面有表列出一致与非一致的比较),还有这篇文章讲的很好:保护模式下如何寻址

SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT


这行代码看起来是DESC_VIDEO这个描述符相对于GDT基址的偏移,其实它有一个专门名称:选择子,而且它也不是一个偏移。选择子用来选择描述符表中的一个描述符

在别的地方看到这样一句话:“选择子确定描述符,描述符确定段基地址,段基地址与偏移之和就是线性地址。”

“段:偏移”形式的逻辑地址经过段机制转化成线性地址,而不是物理地址。不过暂时在这里线性地址就是物理地址。

关于A20地址线:8086->80286寻址范围扩大,但是8086只能寻到1MB,如果访问超过1MB的地址,虽然不会发生异常,但是又从0开始寻址,所以为了保证兼容,使用8042键盘控制器来控制第20个地址(从0开始数)。所以为了访问所有内存,需要把A20打开,默认是关闭的。

寄存器cr0的第0位是PE位,此位为0时是实模式,为1时是保护模式。

jmp dword SelectorCode32:0


这个jmp在16位的段中,目标地址却是32位。不能去掉dword,去掉的话编译出来只是16位的代码,如果目标地址的偏移较大,则前半段会被截断。其实dword是NASM提供的,在Linux内核代码中,这个跳转使用DB指令直接写二进制代码的方式来实现的。

一致与非一致

特权级

低->高
特权级

高->低
相同特权

级之间
适用于何种代码
一致代码段YesNoYes不访问受保护的资源和某些类型

的异常处理的系统代码
非一致代码段NoNoYes避免低特权级的程序访问而被

保护起来的系统代码
数据段(总是非一致)NoYesYes
几个指令的含义:

equ——相当于赋值,可以将一个数值或者一个寄存器名赋给一个指定的符号名。

[gs:edi]——段寄存器名:段名,在这里即代表段:偏移

lgdt——可以把GDT描述符表的大小和起始地址存入gdt寄存器中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐