学习x86时,自己写的一个引导,从实时模式到保护模式

来源:互联网 发布:二叉树的遍历算法c加加 编辑:程序博客网 时间:2024/05/17 08:52

关于os的引导

当机器上电或者是硬件复位时,处理器工作在8086处理器的兼容模式即实时模式下,并且从物理地址的oxFFFF0出开始执行软件初始化代码(通常在EPROM中)。软件初始化代码首先必须设置基本系统功能做操必要的数据结构信息,列如处理中断和异常的实时模式IDT(即中断向量表),然后启动设备中读出零磁头,零磁道上的512B个数据放到从0x7c00处,然后跳转到ox7c00处,

一个合格的引导为512字节大小,且以aa55结束

 

预备知识

 

1.禁止中断,

 

2.加载GDTR

 

3.设置CR0PE

 

4.jmp跳转到30位代码

 

 

 

使用的是lgdt加载GDT的基地址到gdtr寄存器中,

 

CR0的格式如下

 

英文

说明

0

PE

是否启用保护模式的标志,为1启用、为0实时模式

1

MP

监控协处理器,用于控制WAIT/FWAIT指令与TS标志交互作用,MP=1表示协处理器不存在,MP=0,则TS标志不会影响WAIT的执行,MPEMTS一般组合使用,见下解

2

EM

是仿真标志。当该位设置时,表示处理器内没有内部或者外部协处理器,执行协处理器指令时会引起设备不存在异常;当清除时,表示系统有协处理器。设置这个标志可以迫使所有的浮点指令使用软件模拟

3

TS

任务已切换,该标志用于推迟保存任务切换时协处理器的内容,知道新任务开始实际执行协处理器执行,处理器在每次的任务切换时都回设置该标志,并且在执行协处理器指令时测试该标志

4

ET

扩展类型标志,为1,表示系统有80387协助处理器存在,并使用32位的协处理器协议,ET=0指明使用80287协处理器,如果仿真位EM=1,则该位将被忽略。在处理器复位操作时,ET位会被初始化指明系统中使用的协处理器类型。如果系统中有80387,则ET=1,否则若有一个80287或者没有协处理器,则ET被设置成0

5

NE

对于intel80486或以上的CPU,错误位标志,当=1时,就启用了x87协处理器错误的内部报告机制,

18

AM

 

31

PG

分页标志,=1;启用分页,=0未使用分页,只用在保护模式中可用,即PE=1时;

 

EMMPTS的组合

 

EM

MP

TS

浮点

WAIT/FWAIT

0

0

0

执行

执行

0

0

1

设备不存在(DNA)异常

执行

0

1

0

执行

执行

0

1

1

DNA异常

DNA异常

1

0

0

DNA异常

执行

1

0

1

DNA异常

执行

1

1

0

DNA异常

执行

1

1

1

DNA异常

DNA异常

 

 

 

 

 

关于全局描述符表的寄存器GDTR的知识

 

1.为什么要使用GDTR

 

GDTR主要是将每一个任务的数据、代码给分割开,从而使在每一个任务的数据和代码不会出现混乱。使每一个任务只能操作自己的数据和执行自己的代码,为实现多人做准备。

 

GDTR的知识

 

GDTR寄存器中用来存放的是GDT描述符表的基地址,

 

每一个GDT描述符逻辑上有三部分组成段基址(Base address)、段限长(limit)、段属性(Attributes)64位,GDT主要有三种类型的描述符代码段、数据段、系统段;

 

下图给出的是GDT的通用格式

 

 

 

 

 

 

 上面的表示的是高四个字节、下面的表示第四个字节

 

基地址=基地址31-24 +基地址23-16 +基地址15-0

 

段限长=段限长19-16 +段限长址15-0

 

注意这里面的+号不是将数值相加,而是两节起来的,如101b+11b=1000b而是101b+11b=10111b

 

AVL

系统可用

P

段存在

B/D

默认大小

S

描述符的类型

0:系统;1:代码或数据

DPL

描述符的特权级别

TYPE

段类型

G

颗粒度

 

 

 

G颗粒度,该字段用来决定段限长的单位,如果颗粒度标志为0,则段限长的单位字节,如果颗粒度标志为1,则段限长的单位为4k,即使段限长*4k

 

DPL字段指明描述符的特权级别,特权范围从0-30级最高,3最低。

 

P段存标志当P=1段在内存中,P=0段不在内存中

 

D/B该位不理解。

 

S描述符类型:0:系统段比如GDTRIDTR,TSS,门,LDTR

 

    1代码或者数据段,堆栈,程序代码,数据。

 

TYPE值与S有关系的,

 

s=0TYPE的类型

 

十进制

11

10

9

8

说明

0

0

0

0

0

Reserved

1

0

0

0

1

16-bit-TSSAvailable

2

0

0

1

0

LDT

3

0

0

1

1

16-Bit-TSSBusy

4

0

1

0

0

16-bit-Call Gate

5

0

1

0

1

Task Gate

6

0

1

1

0

16-bit Interrupt Gate

7

0

1

1

1

16-bit-Trap-Gate

8

1

0

0

0

Reserved

9

1

0

0

1

32-bit-TSSAvailable

10

1

0

1

0

Reserved

11

1

0

1

1

32-bit TSSBusy

12

1

1

0

0

32-bit Call Gate

13

1

1

0

1

Reserved

14

1

1

1

0

32-bit interrupt Gate

15

1

1

1

1

32-bit Trap Gate

 

S=1TYPE的类型有代码段或者数据段描述符两种,第十一位表示是代码段还是数据段的。当位11的值为1时,位10、位9、位8分别表示的是EWA;

 

作用

说明

10E

表示的扩展方向

值为1:表示向下扩展。

9(W)

是否可写

 

8(A

已访问

 

 

当位11值为0时,位10、位9、位8分别表示的是CRA;

 

作用

说明

10C

一直代码

特权级别,不是很了解的

9(R)

可读

0:只读,仅可以执行

1:执行/可写

8(A

已访问

 

 

根据上面的规则写出对应的GDT就可以了,

下面是代码

View Code 源代码[BITS 16];表示十六位的代码,即使实模式下的  [org   0x7c00];伪操作,将程序放到0x7c00的内存位置,即使引导mov   ax,csmov   ds,axmov   es,axcall   DisplayMsg;调用显示字符的程序,使用中断xor ax, axmov ds, ax cli;关闭中断,跳转到保护模式前,要禁止中断lgdt   [gdtr];加载GDTmov eax, cr0 ;获取当前CR0中的纸           or eax, 1     ;修改PE位为1          mov cr0, eax  ;将修改后的的值放到CR0中,进入实时模式jmp     0x10:Code32;这里使用的是32为的代码,所以与常见的16位实时模式下的jmg跳转代码不一样,16位实时模式使用的是实地址,即使物理地址,而32位的保护模式使用得也是地址跳转,但是使用的是段+偏移地址,0x10表示GDTR表中的第三项,[BITS 32]                       Code32:      mov   ax,0x8mov   gs,axmov   edi,(80*8+9)*2mov   ah,0chmov   al, 'p'mov   [gs:edi],axa:        jmp a                [BITS 16]  DisplayMsg:mov   ax,LoadMsgmov   bp,axmov   cx,18mov   bx,000chmov   dl,010hmov   dh,dlmov   ax,01301hint   10hretLoadMsg:   db   "Load   system   ...... "gdt:        dd 0        dd 0      dw 0x0002      dw 0x8000      dw 0x920b      dw 0x00c0      dw 0x07ff      dw 0      dw 0x9a00      dw 0x00c0gdt_end:gdtr: dw gdt_end - gdt - 1  ;计算gdt的长度  dd gdt   times   510   -   (   $   -   $$)   db   1dw     0xaa55;引导的结束标志



原创粉丝点击