西南交通大学操作系统期末复习总结.docx
- 文档编号:25686953
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:21
- 大小:28.76KB
西南交通大学操作系统期末复习总结.docx
《西南交通大学操作系统期末复习总结.docx》由会员分享,可在线阅读,更多相关《西南交通大学操作系统期末复习总结.docx(21页珍藏版)》请在冰豆网上搜索。
西南交通大学操作系统期末复习总结
1
org07c00h;这是告诉编译器将这段程序加载到内存偏移地址0x7c00处
movax,cs
movds,ax
moves,ax
callDispStr
jmp$
DispStr:
movax,BootMessage
movbp,ax
movcx,16
movax,01301h
movbx,000ch
movdl,0
int10h
ret
BootMessage:
db"hello,osworld!
"
times510-($-$$)db0
dw0xaa55
这是第一章的程序,从中可以看出起始位置是07c00h,程序的结束标志是0xaa55。
$表示当前行被汇编后的地址。
$$表示一个节的开始处被汇编后的地址。
那么$-$$表示本行距离程序开始处的相对距离。
1.对于程序的说明
实际上以上程序只是一个引导扇区(BootSector),不是完整的OS,当计算机电源被打开时,它会加电自检(POST),然后寻找启动盘,如果是从软盘启动,计算机就会检查软盘的0面0磁道1扇区,如果发现它以0xaa55结束,并且包含了少于512字节的执行码,那么BIOS认为它是一个引导扇区。
一旦发现了引导扇区,就将这512字节放入内存地址0000:
7c00处,然后跳转并且移交控制器。
2.制作软盘过程
本身这段程序是boot.asm,是汇编程序,然后使用工具nasm将其转换为boot.bin,
然后使用软盘绝对扇区读写工具将这个文件写到一张空白软盘的第一个扇区。
(.bin文件的说明:
*.bin是Foxbase定义的一种特殊的可执行文件,它同DOS的.com文件类似,区别在于.com文件是从100H开始运行的,而.bin从0开始,.bin的调用参数保存在DS:
BX中。
如果在Foxbase中,你可以使用Call命令调用。
如果你在VFP中,将无法直接调用,只能使用Debug反汇编,分析其功能,然后重新编写.)
3.方括号[]的使用
在NASM中,任何不被方括号[]括起来的标签或变量名都被认为是地址,访问标签中的内容必须使用[]。
3.1认识保护模式
1.对于这一节的程序的理解
数据区:
先是定义了一些描述符(LABEL_GDT,LABEL_DESC_CODE32,LABEL_DESC_VIDEO),
然后定义了GdtPtr,它是一个6字节的数据结构,前两字节表示GDT的界限(即描述符的界限),后4字节表示GDT的基地址(GdtPtr就是用来描述GDT的,会用一个寄存器GDTR来保存它的值)。
然后定义两个选择子,分别指向已定义的描述符。
代码区:
初始化32位代码段描述符,为加载GDTR作准备,加载GDTR:
lgdt[GdtPtr],然后是关中断:
cli,(保护模式下中断处理的机制是不同的,不关中断会出错)打开地址线A20,然后将cr0的PE位置为1(0:
实模式,1:
保护模式),准备切换到保护模式,跳转到保护模式中jmpdwordSelectorCode32:
0
2.Descriptor是一个宏,它是一个8字节的数据结构。
三个描述符组成了一个结构数组。
3.[BITS16]说明这是一个16位的代码段,而[BITS32]是32位的代码段。
程序中的知识点
要搞清楚的有:
GDT是一个索引,指向一个数据结构的表项。
GDT作用:
提供段式存储机制。
程序对GDT做了什么?
jmpSelectorCode32:
0?
GDT
1.在保护模式下,CPU有着巨大的寻址能力(保护模式下为4G,实模式下为1M),并为强大的32位操作系统提供了更好的硬件保障。
2.在保护模式下,段值仅仅变成了一个索引,这个索引指向一个数据结构的一个表项,表项中定义了段的起始地址、界限、属性等内容。
这个数据结构就叫GDT,表项就叫描述符。
3.描述符分为代码段和数据段描述符,还可以分为系统段描述符和门描述符。
4.选择子
TI位0:
GDT,1:
LDT
当TI和RPL都为0时,选择子就变为了偏移。
5."段:
偏移"经过段机制转化为“线性地址”,而不是物理地址。
JMP
1.对于cr0的设置是实模式和保护模式的关键
2.jmpdwordSelectorCode32:
0的作用是将描述符DESC_CODE32对应的段的首地址。
3.为什么那儿有一个dword呢?
(没有dword的话编译出来是16位的代码,而目标地址是32位的。
)
进入保护模式的主要步骤:
1.准备GDT
2.用lgdt加载gdtr
3.打开A20
4.设置cr0的PE位
5.跳转,进入保护模式
描述符的属性
1.P位——存在位。
P=1,表示在段内存中存在;P=0则在内存中不存在。
2.DPL位——描述符特权级。
有0,1,2,3级,数字越小级别越大
3.S位——指明描述符是数据段/代码段(s=1),还是系统段/门描述符(s=0)
3.2保护模式进阶
在这一节中,首先在上一节程序的基础上改写:
(1)跳入保护模式之后再次跳回实模式
(2)读写大地址内存
对于读大地址内容,它是先读,然后再写,然后再读,以此来判断是否可以读写大地址内存。
(注意:
程序中调用子程序时要保存edi的值,要对其进行压栈,所以要用到堆栈,那么在程序中也要有堆栈的描述符和堆栈的选择子。
)
从保护模式跳转到实模式时要复杂一些(从实模式到保护模式只要一个跳转就可以了),我们不能直接从32位的代码段中返回实模式,只能从16位代码段中返回,因为无法从32为代码段返回时cs高速缓存寄存器中的属性符合实模式的要求。
所以增加一个Normal描述符,在返回实模式前把对应的选择子加载到ds、ss和es.
跳回实模式之后要做的事情:
用Normal描述符的选择子加载到ds、ss和es,值cr0的PE=0,关闭A20地址线,开中断STI。
LDT:
局部描述符表
1.LDT与GDT差不多,一个是全局的,一个是局部的。
在代码中也要有一个LDT的描述符和选择子,它的初始化有所不同,有两步:
(1)初始化LDT在GDT中的描述符,
(2)初始化LDT中的描述符。
其中,第二步与GDT类似,多了一个在GDT中定义LDT。
2.LDT与GDT的区别就在于选择子中TI位(0为GDT,1为LDT)
3.在使用LDT时需要先用lldt指令加载ldtr(lgdt加载gdtr)
4.使用LDT的目的:
多任务处理。
5.保护模式“保护”的含义
(1)描述符中的段基址和段界限定义了一个段的范围,对超越段界限之外的地址的访问是被禁止的,这是对段的一种保护。
(2)有点复杂的段属性作为对一个段各个方面的定义规定和限制了段的行为和性质
以上两点是静态的
(3)在涉及特权级的每一步中,处理器都会对CPL,DPL和RPL等内容进行比较,这种比较是动态的。
特权级概述
1.常规保护模式错误
2.将Level0叫做内核,Level1、Level2叫做服务,Level3叫做应用程序。
3.CPL、DPL、RPL
CPL是当前执行的程序或任务的特权级。
通常情况下,CPL等于代码所在段的特权级,
当程序转移到不同特权级的代码段时,处理器将改变CPL。
当处理器访问一个与CPL特权级不同的一致代码段时,CPL不会被改变。
DPL表示段或者门的特权级,下面是各种类型的段或者门的情况
数据段:
高级->低级,相同级别之间
非一致代码段:
相同级别之间
调用门:
与数据段一致
一致代码段和通过调用门访问的非一致代码段:
低级->高级,相同级别之间
TSS(Task-StateStack:
任务状态栈):
与数据段一致
RPL通过选择子的第0位和第1位表现出来的。
操作系统过程往往用RPL来避免低特权级应用程序访问高特权级段内的数据。
4.不同特权级代码之间的转移
程序从一个代码转移到另一个代码之前,目标代码的选择子将会被加载到cs中。
通常使用jmp和call指令来实现转移,转移分为两大类:
(1)直接转移
(2)间接转移
特权级转移
1.如果目标是非一致代码段,要求CPL必须等于目标代码段的DPL,同时要求RPL小于等于DPL。
如果目标是一致代码段,要求CPL大于或者等于目标段的DPL,RPL此时不做检查。
这种直接转移是非常有限的,为了实现不同特权级之间的转移,可以使用门描述符或者TSS。
2.门是一种描述符,它由一个选择子和一个偏移所指定的线性地址。
门的种类:
调用门,中断门,陷阱门,任务门。
作用:
实现不同特权级之间的转换。
在原程序的基础上做的一些工作:
定义门描述符及其选择子,初始化描述符,使用call指令来实现跳转到已经定义好的通过门描述符能够跳转到的目标段。
门实际上是一个入口地址,只不过增加了若干的属性而已。
3.门转移总结:
通过调用门和call指令,可以实现从低特权级到高特权级的转移,无论目标代码是一致的还是非一致的。
我们的目标是从低到高,在从高到低,那么下面的任务就是如何从高到低了。
4.长的和短的jmp和call的区别:
对jmp而言,短跳转对应段内,长跳转对应段间;call要复杂一些,因为call指令会影响堆栈。
5.在使用call指令时,由于某些原因堆栈发生了切换,也就是说call指令执行前后的堆栈已经不是同一个。
Intel提供了一种机制,将堆栈A的诸多内容赋值到堆栈B中。
事实上,由于每一个任务最多可能在4个特权级间转移,所以,每个任务实际上需要4个堆栈,此时要用到一种数据结构,即TSS(Task-StateStack)。
6.综合:
使用调用门的过程实际上分为两个部分,一部分是从低特权级到高特权级,通过调用门和call指令来实现;另一部分则是从高特权级到低特权级,通过ret指令来实现。
7.用程序实现从ring0到ring3
在这里我们需要在原程序的基础上增加ring3的代码段描述符和堆栈段描述符,并添加响应的选择子,
做好工作后,执行一下程序:
pushSelectorStack3
pushTopOfStack3
pushSelectorCodeRing3
push0
retf
为什么会进入ring3呢?
原来程序是执行在ring0的,当使用retf指令后,堆栈将被自动切换到ring3的堆栈段,执行ring3的代码,也就完成了从高特权级项低特权级的转换。
8.从高特权级项低特权级的转换和从低特权级项高特权级的转换都需要用到TSS。
3.页式存储
1.页的概念
页是一块内存,在80386中,大小固定为4K。
在Pentium中,大小可以是2MB或4MB,并且可以访问多余4GB的内存。
2.逻辑地址、线性地址、物理地址
在未打开分页机制的时候,逻辑地址经过分段机制直接转换成物理地址。
打开分页机制后,逻辑地址经过分段机制先是转换成线性地址,
线性地址再经过分页机制转换成物理地址。
3.分页的目的
实际上使用分段机制已经提供了很好的保护机制,
分页的目的在于实现虚拟存储器。
用代码启动分页机制
代码
PageDirBaseequ200000h;页目录开始地址:
2M
PageTblBaseequ201000h;页表开始地址:
2M+4K
。
。
。
LABEL_DESC_PAGE_DIR:
DescriptorPageDirBase,4095,DA_DRW;PageDirectory
LABEL_DESC_PAGE_TBL:
DescriptorPageTblBase,1023,DA_DRW|DA_LIMIT_4K;PageTables
。
。
。
SelectorPageDirequLABEL_DESC_PAGE_DIR-LABEL_GDT
SelectorPageTblequLABEL_DESC_PAGE_TBL-LABEL_GDT
。
。
。
;启动分页机制--------------------------------------------------------------
SetupPaging:
;为简化处理,所有线性地址对应相等的物理地址.
;首先初始化页目录
movax,SelectorPageDir;此段首地址为PageDirBase
moves,ax
movecx,1024;共1K个表项
xoredi,edi
xoreax,eax
moveax,PageTblBase|PG_P|PG_USU|PG_RWW
.1:
stosd
addeax,4096;为了简化,所有页表在内存中是连续的.
loop.1
;再初始化所有页表(1K个,4M内存空间)
movax,SelectorPageTbl;此段首地址为PageTblBase
moves,ax
movecx,1024*1024;共1M个页表项,也即有1M个页
xoredi,edi
xoreax,eax
moveax,PG_P|PG_USU|PG_RWW
.2:
stosd
addeax,4096;每一页指向4K的空间
loop.2
moveax,PageDirBase
movcr3,eax
moveax,cr0
oreax,80000000h
movcr0,eax
jmpshort.3
.3:
nop
ret
;分页机制启动完毕----------------------------------------------------------
代码过程说明:
首先定义页目录项(PDE)和页表项(PTE)的描述符和选择子,然后将es:
edi指向页目录表的开始。
经过1024个循环之后,将所有PDE赋值完,他们属性相同,都是指向可读可写的用户级别页表。
然后将es:
edi指向页表的开始。
经过1024*1024个循环,将所有PTE赋值完,他们属性相同,都是指向可读可写的用户级别页。
下面就是让cr3(cr3是一个指向PDE的页目录表,又叫PDBR(Page-DirectoryBaseRegister))指向页目录,然后设置cr0的PG位(cr0的PG位为最高位,为1表示分页机制启动,为0表示未启动),这样,分页机制就完成了。
关于PDE、PTE的一些说明
1.P位——存在位。
P=1表示在物理内存中存在;P=0表示不存在,如果处理器视图访问此页,那么将会产生页异常。
2.A位——指示页或页表是否被访问
3.处理器会将最近常用的页目录和页表项保存在一个叫做TLB(转移后背缓冲区)的缓冲区中,只有当TLB中找不到被请求也的转换信息时,才到内存中去找,这样加快了速度。
4.当页目录或页表项被更新时,OS会马上让TLB无效。
当cr3被加载时,所有TLB都会自动失效,除非页或页表的G位被设置。
克勤克俭用内存
这部分的目的:
在前面的是4KB->4MB->4GB,但是内存也不一定那么大,如果内存本身就很小,几十MB,那么你的页表(4MB)就占了很多,所以有必要知道内存大小。
获取内存大小的方法:
使用中断15h
我们想得到内存的信息,那么采用的方法是将得到的描述信息保存到一段缓冲区中。
因为一个ARDS的大小是20字节,那么这里定义一个256字节的缓冲区(实际上也是不确定其大小的)。
然后待会儿可以显示出来。
得到内存信息代码:
_MemChkBuf:
times256db0;内存缓冲区
。
。
。
;得到内存数
movebx,0
movdi,_MemChkBuf
.loop:
moveax,0E820h
movecx,20
movedx,0534D4150h
int15h
jcLABEL_MEM_CHK_FAIL;该语句就是判断是否有进位
adddi,20
incdword[_dwMCRNumber];用于记录循环次数,也就是地址范围描述符结构的个数
cmpebx,0
jne.loop
jmpLABEL_MEM_CHK_OK
LABEL_MEM_CHK_FAIL:
movdword[_dwMCRNumber],0
LABEL_MEM_CHK_OK:
代码说明:
地址范围描述符(ARDS)的大小就是20个字节,所以di每次增加20,在代码中es:
di的赋值似乎是BIOS自动填充的,没有手动填充的痕迹。
跳出循环的条件是ebx=0或者CF没有进位(CF=0)
1.关于ARDS的type的说明
1)AddressRangeMemory可以使用
2)AddressRangeReserved不可以使用
2.我们处理得到内存的大小外,还得到了可用内存的分布信息。
并且内存的分布可能是不连续的。
3.在得到内存大小后,将该值除以4MB,就可以得到PDE的个数,将PDE初始化,也就是将1024替换掉。
然后是要初始化PTE,只需要将PDE的个数*1024即可。
进一步体会分页机制
在这里我们要实现:
先执行某个线性地址处的模块,然后通过改变cr3来转换地址映射关系,
再执行同一个线性地址处的模块,由于地址映射已经改变,所以两次得到的应该是不同的输出结果。
其实分页机制的好处还有,程序使用的都是线性地址,而不是直接的物理地址。
此时OS为应用程序提供了一个不依赖于硬件(物理内存)的平台。
在3.3中,是在实模式下得到的内存信息,然后在保护模式下将其显示出来。
而在保护模式下,原来的中断向量表由IDT(InterruptDescriptorTable,中断描述符表)代替,IDT中的描述符可以是以下三种之一:
(1)中断门描述符
(2)陷阱门描述符
(3)任务门描述符
IDT的作用是将每一个中断向量和描述符对应起来。
在前面使用调用门是通过call指令,这里使用中断门和陷阱门是使用int指令。
3.4中断和异常机制
1.中断:
中断通常在程序执行时因为硬件而随机发生,他们通常用来处理处理器外部的事件,比如外围设备的请求。
软件通过执行intn指令也可以产生中断。
(软硬件都可以)
2.异常:
异常通常在处理器执行指令过程中检测到的错误时发生,比如遇到除零的情况。
(多指软件方面)
问题:
处理器可以对何种类型的通知作出反应。
接到某种通知时做出何种反应。
3.Fault(错误)、Trap(陷阱)和Abort(终止)三种类型的异常
①Fault是一种可以被更正的异常,而且一旦被更正,程序可以不失连续性地继续执行。
当一个Fault发生时,处理器会把产生fault指令之前的状态保存起来。
异常处理程序的返回地址将会是fault的指令,而不是其后的那条指令。
②Trap是一种在发生trap指令执行后立即被报告的异常,他也允许程序或任务不失连续性地继续执行。
异常处理程序的返回地址将会是产生trap的指令之后的那条指令。
③Abort是一种不总是报告精确异常发生的位置的异常,它不允许程序或任务继续执行,而是用来报告严重错误的。
写一个硬件中断程序,所做的工作有两点:
(1)设置8259A
使用OCW1、OCW2、OCW3的情况,
一是屏蔽或打开外部中断
二是发送EOI给8259A以通知它中断处理结束
(2)建立IDT(这部分跟建立GDT或LDT差不多)
时钟中断实验
1.外部可屏蔽中断的发生受到两个因素的影响,只有当IF=1,并且IMR(OCW1)位为0时才发生。
2.从中断或异常返回时必须使用指令iretd,它与ret相似,只是它同时会改变eflags的值。
iretd执行时ErrorCode不会被自动从堆栈中弹出,所以,执行它之前要先将它从栈中清除。
3.中断门和陷阱门的区别:
中断门会影响标志IF(由中断门引起的中断会复位IF,因为可以避免其他中断干扰当前中断的处理。
随后的iret指令会从堆栈上恢复IF的原值)。
陷阱门不会改变IF。
保护模式下的I/O
1.对I/O的限制是保护模式的内容,可以通过两个方面的限制来实现:
IOPL和I/O许可位图
2.IPOL位于eflags的12、13位
指令in,ins,out,outs,cli,sli只有在CPL<=IPOL时才能执行,这些指令叫做I/O敏感指令,如果低特权级的指令试图访问这些I/O指令将会导致常规保护错误。
可以改变IPOL的指令有popf和iretd,只有运行在ring0的程序才可以将其改变。
popf同时可以用来改变IF。
3.I/O许可位图必须以0FFH结尾。
3.6保护的种类
1.在GDT、LDT以及IDT中,每一个描述符都有自己的界限和属性等内容,是对描述符所描述对象的一种限定和保护。
2.分页机制中的PDE和PTE都含有R/W和U/S位,提供了页级保护。
3.页式存储的使用使应用程序的是线性地址空间不是物理地址,于是物理内存就被保护了起来。
4.中断不再像是模式下一样使用,也提供特权检验等内容。
5.I/O指令不再随便使用,于是端口被保护了起来。
6.在不同的特权级之间转换时,CPL、DPL、RPL、IOPL等内容会进行非常严格的检验。
4突破512字节限制
一个OS从开机到开始运行,大致经历了以下阶段:
引导——>加载内核如内存——>跳入保护模式——>开始执行内核
而引导扇区(BootSector)只有512字节,要完成以上全部过程是不行的,大小受到了限制。
该怎么办呢?
我们可以采用用BootSector来引导把Loader加载入内存并且把控制权交给它,让它来实现加载内核等的工作。
FAT12
1.FAT12是文件系统,磁盘分层:
扇区:
磁盘上的最小数据单元
簇:
一个或多个扇区
分区:
通常指整个文件系统
2.引导扇区位于FAT12的第0个扇区,在这个扇区中有一个很重要的数据结构叫BPB。
引导扇区中记录了FAT12的信息,比如BPB_RootEntCnt表示根目录文件数最大值。
还有就是每扇区字节数,每簇扇区数等。
3.规定Loader位于根目录区,根目录区的每一个条目占用32字节,有文件名、属性、大小等信息,那么找Loader就要到根目录区中去一个一个的找。
4.数据区的第一个簇的簇号是2,而不是0或1。
5.根目录区的开始扇区号为19(扇区大小可以看BPB_BytsPerSec,书上是512字节),
因为根目录区的大小是不确定的,那么数据区的开始位置也是不确定的。
数据区的开始扇区号=19+根目录区的大小
根目录区的大小=(BPB_RootEntCnt*32+BPB_BytsPerSec-1)/BPB_BytsPerSec
从中可以看出,根目录区是保存文件的属性信息,而数据区是保存文件的内容信息的。
6.现在有一个问题,那就是既然通过上述方法都是可以找到文件及其内容的,那又何必要
什么FAT项呢!
?
(实际上,对于小于512字节的文件来说,上述方法就可以解决了,而对于大于512字节的文件来说,我们需要FAT表来找到所有的簇(扇区)。
)
7.FAT的结构——每12位称为一个FAT项,代表一个簇。
第0个和第1个不实用,与数据区对应。
8.FAT值的说明
FAT项的值代表的是文件的下一个簇号,但是如果值大于或等于0xF
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 西南交通大学 操作系统 期末 复习 总结