30天自制操作系统读书笔记(六)

首先先整理下(转自谷月轩的博客)

现在我们拥有这么9个文件:

  • ipl10.nas    InitialProgramLoader, 占用了软盘的第一个扇区并符合启动盘的规范, 默认被载入地址是0x7c00 到 0x7e00, 负责将10个柱面读入到0x8200到0x34fff (10个柱面共10*2*18 = 360 个扇区但是第一个没有被读入);
  • asmhead.nas     包含一些暂时未知的设定;
  • naskfun.nas     包含供C语言程序使用的汇编函数;
  • bootpack.h     各种常量定义, 函数定义;
  • hankaku.txt     字库文件;
  • fifo.c         一个完整的循环队列的实现, 用于中断的缓冲;
  • graphic.c     提供绘图函数, 绘制系统界面和指针, 打印字符;
  • dsctbl.c     GDT(全局符号描述符表) 和 IDT(中断描述符表) 的设定;
  • int.c         Interrupt Service Routines 的处理.

 

 

恩,接下里我们补坑。

介绍下GDT和IDT

 

DT 全称是全局段描述符表, 用来提供程序执行是需要的关于内存的各种信息,大小为8字节, 包含了: 段的大小; 段的起始地址; 段的管理属性等信息。(具体的作用请百度GDT详解。下文只是针对书本代码进行一些简单的解释。)

C语言描述:

struct SEGMENT_DESCRIPTOR {

         short limit_low, base_low;

         char base_mid, access_right;

         char limit_high, base_high;

};

 

 

我们知道现在段地址是32位的。在这个结构里用base表示,但是它分成了3段

Low(2字节) mid(1字节) high(1字节) 刚好32位。 

为什么要分成3段呢?为了兼容80286时代的CPU。

 

段上限 limit,这个看上去占了24个字节,但是limit_high中的上4位,用来保存段属性了,所以只能用20 位。

 

那还有剩下12位的段属性。

高四位称为“扩展访问权”。这4位是由“GD00”构成的,其中G是指刚才G bit,D指段模式,1表示32位。

低8位表示一些权限。不细写了。

 

struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;

         struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) 0x0026f800;

 

 

这2个地址是作者随意的,反正这里面没有其他程序在占用。。。

 

for (i = 0; i < 8192; i++) {

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

         }

 

挨个初始化

 

 

 

 

 

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

{

//上面说了limit只占20位,所以只能表示最多1M的空间

//所以当输入的limit大于20位时,就执行页模式(不细写了)就要将G bit置1然后limit右

//移4位。

         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) & 0x0f) | ((ar >> 8) & 0xf0);

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

         return;

}

 

 

 

load_gdtr(0xffff, 0x00270000);

至于这句嘛,很简单因为C语言不能直接操作cpu所以,只能改用汇编写入gdtr这个寄存器了。

 

还有就是IDT,他和GDT差不多,各位之前学习汇编的时候一定已经接触过了,毕竟应该没有哪本汇编教材不介绍大名鼎鼎的int中断吧。

 

PIC:

 处理中断的辅助芯片。 与CPU直接相连的PIC成为主PIC,与主PIC相连的PIC称为从PIC

,主PIC负责处理第0到第7号中断信号,从PIC负责处理第8到第15号中断信号。

从PIC通过第二号IRQ与主PIC相连。

 

 

 

void init_pic(void)

    /* PIC初始化*/

{

    io_out8(PIC0_IMR, 0xff ); //禁止主PIC的所有中断

    io_out8(PIC1_IMR, 0xff ); //禁止从PIC的所有中断

 

    // 主PIC设定

    io_out8(PIC0_ICW1, 0x11 ); //边沿触发模式 (edge trigger mode)

    io_out8(PIC0_ICW2, 0x20 ); //IRQ0~7 由 INT 20~27 接收

    io_out8(PIC0_ICW3, 1 << 2); //PIC1从PIC由IRQ2 连接

    io_out8(PIC0_ICW4, 0x01 ); //无缓冲区模式

 

    //从PIC设定

    io_out8(PIC1_ICW1, 0x11 ); //边沿触发模式 (edge trigger mode)

    io_out8(PIC1_ICW2, 0x28 ); // IRQ0~7 由 INT 28~2f 接收

    io_out8(PIC1_ICW3, 2 ); //PIC1由IRQ2 连接

    io_out8(PIC1_ICW4, 0x01 ); //无缓冲区模式

    io_out8(PIC0_IMR, 0xfb ); //11111011 PIC1 以外全部禁止

    io_out8(PIC1_IMR, 0xff ); //11111111 禁止所有中断

    return;

}

 

介绍下PIC的寄存器:

 

IMR :interrupt mask register   “中断屏蔽寄存器”

8位对应8路IRQ信号,置1表示忽略该路信号。

 

ICW :initial control word   “初始化控制数据”

ICW 有4个,每个1个字节。

ICW 1 和ICW 4 声明了主板配线方式( = = 完全不懂哎);

ICW 3 是主从设定, 表示触发器的哪一位连着从触发器; (一般是IRQ2 啦);

ICW 2 决定IRQ以哪一个中断号通知CPU, INT 0x0~0x19 不能被使用.

 

 

到现在为止准备工作算是完成了。

今天接下来的东西只介绍了那么一点,写成笔记也没什么必要,等完成的差不多了在一块整理吧!

        

 

posted @ 2015-04-20 19:56  _如此甚好  阅读(356)  评论(0编辑  收藏  举报