我在学习昨天上传的进入保护模式代码时发现了几个错误,在此进行了更正并增加了很多注释,以便于读者理解。同时我将上传阅读操作系统概念第一章所记录的全部笔记。顺便吐槽一句,我的CS老师还蛮严格的…
During my review about the jmp to protected mode code which I upload yesterday, I found few mistakes(Made by me), thus I would like to correct it which could help readers to comprehend. At the same time, I will upload my study note about I taken when I was reading ‘Operating System Concept’. And in the end, I have to say that…you know, my CS teacher is quite strict when he is scoring us…
%include "pm.inc"
org 07c00h
jmp LABEL_BEGIN
[Section .GDT]
;GDT
; 段基址, 段界限, 属性
LABEL_GDT: Descriptor 0, 0, 0 ;空描述符
LABEL_DESC_CONDE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32 ;非一致代码段
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ;显存首地址
;GDT结束
GdtLen equ $ - LABEL ;GDT长度
Gdtptr dw GdtLen - 1 ;GDT界限
;GDT选择子
SelectorCode32 equ LABEL_DESC_CONDE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
;END of [SECTION .gdt]
先来看这段代码,其中Descriptor是在pm.inc中定义的宏,代表一段数据结构,大小为8字节
; usage: Descriptor Base, Limit, Attr
; Base: dd
; Limit: dd (low 20 bits available)
; Attr: dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3
dw %1 & 0FFFFh ;段基址1
dw %2 & 0FFFFh ;段界限1
db (%1>>16) & 0FFh ;段基址2
dw ((%2>>8) & 0F00h) | (%3 & 0F0FFh) ;属性1+段界限+属性2
db (%1>>24) & 0FFh ;段基址3
%endmacro ;共 8 字节
三个并列的Descriptor是个结构数组,称为GDT;GdtLen是GDT的长度,GdtPtr也是个小的数据结构,它有6字节,前2字节是GDT的界限,后4字节是GDT的基地址
“保护模式下“段”的概念发生了变化。实模式下,段值还是可以看做是地址的一部分的,段值为XXXXh表示以XXXX0h 开始的一段内存。而保护模式下,虽然段值仍然由原来16位的cs、ds等寄存器表示,但此时它仅仅变成了一个索引,这个索引指向一个数据结构的一个表项,表项中详细定义了段的起始地 址、界限、属性等内容。这个数据结构,就是GDT(实际上还可能是LDT,这个以后再介绍)。GDT中的表项也有一个专门的名字,叫做描述符(Descriptor)”
Descriptor这个宏用比较自动化的方法把段基址、段界限和段属性安排在一个描述符中合适的位置。DESC_DUMMY、DESC_CODE32和DESC_VIDEO。其中DESC_VIDEO的段基址是0B8000h,这个描述符指向的正是显存。
GDT中的每一个描述符定义一个段,那么cs、ds等段寄存器是如何和这些段对应起来的呢?[SECTION.s32]这个段中有两句代码是这样的(第80行和第 81行):
mov ax, SelectorVideo
mov gs, ax
段寄存器gs的值变成了SelectorVideo,我们在上文中可以看到,SelectorVideo是这样定义的(第25行):
SelectorVideo equ LABEL_DESC_VIDEO-LABEL_GDT
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax, cs
mov ds, ax
mov es, as
mov ss, ax
mov sp, 0100h
;初始化32位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_DESC_CONDE32
mov byte [LABEL_DESC_CONDE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CONDE32 + 4], al
mov byte [LABEL_DESC_CONDE32 + 7], ah
;LABEL_SEG_CODE32的物理地址赋给eax
;然后把它分成三部分赋给描述符DESC_CODE32中的相应位置
;为加载GDTR做准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT
;eax <- gdt基地址
mov dword [GdtPrt + 2], eax
;[GdtPtr + 2] <- gdt基地址
;Gdtptr结构从第三个字节开始存储描述符索引
lgdt [GdtPtr]
;将GdtPtr加载到gdtr
;关中断
cli
;打开地址线A20
in al, 92h
or al, 00000010b
;准备切换到保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
;寄存器cr0的第0位是PE位
;此位为0时,CPU运行于实模式,为1时,CPU运行于保护模式
;真正进入保护模式
jmp dword SelectorCode
;执行这一句会把SelectorCode32装入cs,放在16位的段中
;目标地址却是32位的,它是Mixing 16 and 32 Bit Code
;END of [SECTION .s16]
//8086中,“段:偏移”这样的模式能表示的最大内存是FFFF:FFFF,即10FFEFh。可是8086只有20位的地址总线, 只能寻址到1MB,那么如果试图访问超过1MB的地址时会怎样呢? 实际上系统并不会发生异常,而是回卷(wrap)回去,重新从地址零开始寻址。可是,到了80286时,真的可以访问到1MB以 上的内存了,如果遇到同样的情况,系统不会再回卷寻址,这就造成了向上不兼容,为了保证百分之百兼容,IBM想出一个办法,使用8042键盘控制器来控制第20个(从零开始数)地址位, 这就是A20地址线,如果不被打开,第20个地址位将会总是零。
[SECTION .s32]
[BITS 32]
mov ax, SelectorVideo
mov gs, ax
;视频段选择子(目的)
mov edi, (80 * 11 + 79) * 2
;屏幕第11行,第79列
mov ah, 0ch
;0000:黑底 1100:红字
mov al, 'P'
mov [gs:edi], ax
;到此停止
jmp $
SegCode32Len equ $ - LABEL_SEG_CODE32
;END of [SECTION .s32]
Operating System Concept Note:
多任务系统(Parallel system)或称为tightly coupled system
有多个紧密通信的CPU,共享计算机总线,时钟和内设、外设
其优点:1. 增加吞吐量,通过增加处理器数量,在更短时间内做更多事情。但用N个处理器加速比不是N,而比N笑。当多个CPU都在做一件事情时,为了使各部分都能正确工作,会产生一定额外开销,并且存在对共享资源的争抢。就像是N个程序猿一起工作不能完成N倍个程序猿的单个程序猿工作量
2. 规模经济。多处理器系统节省资金,因为他们共享外设,大容量存储和电源供给
3. 增加可靠性,功能分贝在多个处理器上,处理器失灵不会使得整个系统停止只会变慢
HP NonStop系统通过冗余的硬件和软件保证在故障时仍然能继续工作。其具备多对CPU,同步工作,每一对处理器都各自执行自己的指令并比较结果。如果结果不同,两个均停止,然后执行的进程倍送入另一对CPU中,重新执行刚才的指令
多处理器系统主要有两种类型,非对称处理(asymmetric multiprocessing),即每个处理器都有各自特定的任务。一个主处理控制系统,其他处理器或者向主处理器要任务或做预先定义的任务。这种方案称为主从关系,主处理器调度从处理器并安排任务
另一种对称多处理(symmetric multiprocessing),每个处理器都要完成操作系统中的内容
1.3 操作系统结构
操作系统最重要的是多道程序处理能力。单个用户不能使CPU和I/O设备都忙,多道程序设计通过组织作业,使CPU永远有一个任务可执行。其思想是:在等待一个作业执行结束时,操作系统自动选择内存中的一个作业并开始执行,最终,第一个作业完成等待并重新获得CPU