读《自己动手写操作系统》
时间:2009-04-14 来源:yinshen
Register
AX |
BX |
CX |
DX |
General purpose register
SP |
BP |
SI |
DI |
IP |
F |
CS |
DS |
SS |
ES |
FS |
GS |
Segment register
CR0 |
CR1 |
CR2 |
CR3 |
CR4 |
Control Resgister
访问代码段:CS:IP
访问堆栈段:SS:SP SS:BP
访问数据段:DS:BX DS:SI DS:DI
Addressing mode
Immediate Addressing MOV BX,1234H
Register Addressing MOV DS,AX
Direct Addressing MOV AL, [1234H] MOV AX,DS:[1234H]
Indirect Addressing MOV AX,[BX]
Based Addressing MOV AL,[BP][80H]或 MOV AL, [BP+80H]
Indexed Addressing MOV AX,ARRAY1[SI]
Based Indexed Addressing
进入保护模式
要进入保护模式,我们必须先运行在实模式下,所以我们求助16位的dos系统。
程序pmtest1.asm
Section gdt
.s16
.s32
流程
Jmp到16位代码
初始化 32 位代码段描述符
准备切换到保护模式
jmp dword SelectorCode32:0
32bit代码用段式存储,实现打印P
保护模式进阶:读写5MB内存并返回实模式
程序pmtest2.asm
Section
gdt
data1
gs
s16
s32
s16code
流程:
16bit代码.s16
切换到保护模式,读写5MB内存,并打印出来
跳转到.16code,切换到实模式
回到dos
局部任务LDT
ldt不但是gdt中的一个描述符,还需要一个新的节
程序pmtest3.asm
.gdt
data1
gs
s16
s32
s16code
ldt
la
流程:
16bit代码.s16
切换到保护模式,.32
跳转到局部任务.la,打印L
跳回16bit代码.s16code,
返回实模式
特权级
调用门初体验
程序pmtest4.asm
.gdt
.data1
.gs
.s16
.s32
.sdest
.s16code
.ldt
.la
流程:
16bit代码.s16
切换到保护模式,.32
call SelectorCallGateTest:0 ; 测试调用门(无特权级变换),将打印字母 'C'。
回到.32
jmp SelectorLDTCodeA:0 ; 跳入局部任务,将打印字母 'L'。
跳回16bit代码.s16code,
返回实模式
特权级切换
CPL CS,SS
DPL descriptor
RPL selector
当当前代码段试图访问一个段或门时,会将当前CPL和门selector的RPL与要访问段的DPL进行比较,比较规则如下:
数据段
只能高-> 低,或同级之间
代码段:
一致代码段:同级之间或低->高
非一致代码段:在不采用调用门时, 只能在相同级别之间的代码切换
采用调用门时,不论是否一致代码段,都可以同级之间或低->高
变换特权级
我们的程序一直是运行在最高的ring0级别,我们现在让它先进入ring3,再切换到到ring0,最后回到ring3,
.16->gate->
程序pmtest5.asm
.gdt
.data1
.gs
.s3; 堆栈段ring3
.tss
.s16
.s32
.sdest
.s16code
.ldt
.la
.ring3
流程:
16bit代码.s16
切换到保护模式,.32
push… retf; ring0->ring3;从高到低。retf前我们手动把cs,eip,ss,esp压栈
call SelectorCallGateTest:0 ; 测试调用门(有特权级变换),将打印字母 'C'。从低到高。这个时候会用到TSS. call自动把cs,eip,ss,esp压栈
retf ;回到.ring3,从高到低
jmp SelectorLDTCodeA:0 ; 跳入局部任务,将打印字母 'L'。
跳回16bit代码.s16code,
返回实模式