1个人开发操作系统之GDT和IDT的初始化

内存管理时,不让多进程的程序出现内存冲突的一解决方案是Segmentation4GB的内存可以任何分割,每块的初始地址都是0。另外还有一种复杂的内存管理方案,既Paging,目前主流的操作系统都是采用这种方式。本文的OS为了实现简单,只采用Segmentation方案。

我们规定1Segmentation的信息有:

l         Size

l         初始地址

l         属性(读写权限等)。

每个Segementation信息占8Byte,既64bit。我们把所有的Segment编号,并把编号保存在CPU内的16segment register里。Segment register可以处理08191segment 本来16位的register应该可以处理065535segment,但是因为register的低3为不能使用,所以最多只到8191。为了保存8192segment(每个8bytes),需要64KB的容量,CPU是无法保存这么多数据的,因此需要内存的帮助。GDT[gobal (segment) descriptor table]的缩写,它保存所有segment的信息。Segment的初始地址和有效设定个数保存在CPUGDTR寄存器内。另外一个IDT[interrupt descriptor table]的缩写,用来处理一些内部或外部的中断。例如键盘,鼠标,软驱,硬盘,CDROM,网卡等。IDT可以处理0255编号的中断,例如当123号中断发生时,调用XXX函数。IDT的信息和GDT相似,也是每个8bytes。本系统的GDT分配在内存的0x270000x27ffffIDT0x 26f 8000x26ffff,占2KB

我们将Segment定义为:

struct SEGMENT_DESCRIPTOR {

              short limit_low, base_low;

              char base_mid, access_right;

              char limit_high, base_high;

};

Segment信息的初始地址由32bit组成,成为Base地址,分为3个部分,low2byte),mid1byte),high1byte),如此分割是为了兼容80286 CPU

Segment信息的大小成为LimitLimit最大可以为4GB,当然是在32位机。这样就需要4Byte,和Base地址一共需要8byte,但这样就没有保存属性的位置。为了留给属性空间,只能给Limit 20bit,最大能表示1MB,当然这样是不能满足目前主流的32bit机的。Intel为了解决这个问题,规定了在属性里留有1位称为G bitG表示granularity,粒度),limit的单位不是Byte,而是PagePCCPU1Page表示4KB。这样4KB*1MB=4GB。为了能表示20bitLimit,我们使用2Byte。其中多出的4bit用来表示属性。

Segment的属性由Limit多出的4bit加上剩下的8bit表示,也称访问权限。访问权限的构成:

XXXX0000XXXXXXXXX代表01

4bit386以后使用的扩张访问属性,由[GD00]构成,G表示上面提到的粒度,D表示Segment mode1表示32位机,0表示16位机。下8bit继承80286时代的Segement属性。8bit的属性内容非常多,在这里,我们常用的有如下几个:

000000000x00):未使用的Descriptor table

100100100x92):系统专用,可读写,不能执行

100110100x 9a ):系统专用,可执行,可读,不可写

111100100xf2):应用程序使用,可读写,不可执行。

111110100xfa):应用程序可用,可执行,可读,不可写。

属性规定了系统和应用程序使用的读写执行权限。系统模式称为Ring0,应用程序模式称为Ring3,中间的Ring1Ring2模式是系统服务。Ring0管理Ring3,例如,Ring3的应用程序在请求Load LGDT时,操作系统将否决该请求,以保证系统的安全性。下面是新增加的源代码文件。

 

/*boot.h*/

#define AR_DATA32_RW  0x4092

#define AR_CODE32_ER 0x 409a

#define ADR_BOTPAK                   0x00280000

#define LIMIT_BOTPAK  0x0007ffff

#define LIMIT_GDT                       0x0000ffff

 

#define ADR_IDT                                         0x 0026f 800

#define LIMIT_IDT                        0x000007ff

 

 

struct SEGMENT_DESCRIPTOR {

              short limit_low, base_low;

              char base_mid, access_right;

              char limit_high, base_high;

};

 

 

struct GATE_DESCRIPTOR {

              short offset_low, selector;

              char dw_count, access_right;

              short offset_high;

};

 

void init_gdtidt(void);

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);

void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);

 

/*gldt.c*/

#include "boot.h"

 

void init_gdtidt(void)

{

              struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;

              struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) ADR_IDT;

              int i;

 

              /*GDT Init*/

              for (i = 0; i <= LIMIT_GDT / 8; i++) {

                            set_segmdesc(gdt + i, 0, 0, 0);

              }

             

              /*set all memory into data segement*/

              set_segmdesc(gdt + 1, 0xffffffff,   0x00000000, AR_DATA32_RW);

             

              /*set this segemnt to code segment that can be executed by system*/

              set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);

             

              load_gdtr(LIMIT_GDT, ADR_GDT);

 

              /*IDT Init*/

              for (i = 0; i <= LIMIT_IDT / 8; i++) {

                            set_gatedesc(idt + i, 0, 0, 0);

              }

              /*implemented in func.s*/

              load_idtr(LIMIT_IDT, ADR_IDT);

 

              return;

}

 

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)

{

              if (limit > 0xfffff) {

                            ar |= 0x8000; /* G_bit = 1 */

                            limit /= 0x1000;

              }

              sd->limit_low    = limit & 0xffff;

              sd->base_low     = base & 0xffff;

              sd->base_mid     = (base >> 16) & 0xff;

              sd->access_right = ar & 0xff;

              sd->limit_high   = ((limit >> 16) & 0x 0f ) | ((ar >> 8) & 0xf0);

              sd->base_high    = (base >> 24) & 0xff;

              return;

}

 

void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)

{

              gd->offset_low   = offset & 0xffff;

              gd->selector     = selector;

              gd->dw_count     = (ar >> 8) & 0xff;

              gd->access_right = ar & 0xff;

              gd->offset_high  = (offset >> 16) & 0xffff;

              return;

}

 

;func.s

;Colimas Simple OS

 

[BITS 32]        

                            GLOBAL             _io_hlt, _io_cli, _io_sti, io_stihlt

                            GLOBAL             _io_in8,  _io_in16,  _io_in32

                            GLOBAL             _io_out8, _io_out16, _io_out32

                            GLOBAL             _io_load_eflags, _io_store_eflags

                            GLOBAL             _load_gdtr, _load_idtr                    

segment .text

 

 

_io_hlt:  ; void io_hlt(void);

                            HLT

                            RET

 

_io_cli:   ; void io_cli(void);

                            CLI

                            RET

 

_io_sti:   ; void io_sti(void);

                            STI

                            RET

 

_io_stihlt:             ; void io_stihlt(void);

                            STI

                            HLT

                            RET

 

_io_in8:  ; int io_in8(int port);

                            MOV                    EDX,[ESP+4]                    ; port

                            MOV                    EAX,0

                            IN                        AL,DX

                            RET

 

_io_in16:              ; int io_in16(int port);

                            MOV                    EDX,[ESP+4]                    ; port

                            MOV                    EAX,0

                            IN                        AX,DX

                            RET

 

_io_in32:              ; int io_in32(int port);

                            MOV                    EDX,[ESP+4]                    ; port

                            IN                        EAX,DX

                            RET

 

_io_out8:              ; void io_out8(int port, int data);

                            MOV                    EDX,[ESP+4]                    ; port

                            MOV                    AL,[ESP+8]                       ; data

                            OUT                    DX , AL

                            RET

 

_io_out16:            ; void io_out16(int port, int data);

                            MOV                    EDX,[ESP+4]                    ; port

                            MOV                    EAX,[ESP+8]                    ; data

                            OUT                    DX,AX

                            RET

 

_io_out32:            ; void io_out32(int port, int data);

                            MOV                    EDX,[ESP+4]                    ; port

                            MOV                    EAX,[ESP+8]                    ; data

                            OUT                    DX,EAX

                            RET

 

_io_load_eflags:   ; int io_load_eflags(void);

                            PUSHFD                           ; PUSH EFLAGS

                            POP                     EAX

                            RET

 

_io_store_eflags:  ; void io_store_eflags(int eflags);

                            MOV                    EAX,[ESP+4]

                            PUSH    EAX

                            POPFD                ; POP EFLAGS

                            RET

 

;09/03

 

_load_gdtr:                        ; void load_gdtr(int limit, int addr);

                            MOV                    AX,[ESP+4]                       ; limit

                            MOV                    [ESP+6],AX

                            LGDT    [ESP+6]

                            RET

 

_load_idtr:                         ; void load_idtr(int limit, int addr);

                            MOV                    AX,[ESP+4]                       ; limit

                            MOV                    [ESP+6],AX

                            LIDT     [ESP+6]

                            RET

_load_gdtr函数的参数是LimitBase地址,GDTR48位寄存器,不能直接使用Mov指令,这个寄存器的后16bit,也就是内存的最初2byte表示Limit,剩下的4byte表示Base地址。[ESP+4]表示limit[ESP+8]表示base地址。因为我们不需要Limit[ESP+4][ESP+6]的值,只需要将[ESP+6]代入LGDT_load_idtr_load_gdtr相同。

 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值