[读书笔记]30 天自制操作系统 day6 分割编译与中断处理

1. 分割源文件

  1. 由于原先的bootpack.c 太过冗长, 将他分割成几个部分
    这里写图片描述
  2. 同时为了节省声明所占空间, 使用 头文件

2. 整理Makefile

  1. 将多个类似的编译规则, 使用一般规则进行合并, 简化书写
  2. 一般而言, 普通规则的优先级比一般规则要高 (类似于 C++ 模板 和 偏特化情形)

4. 意犹未尽

4.1 load_gdtr

_load_gdtr:     ; void load_gdtr(int limit, int addr);
        MOV     AX,[ESP+4]      ; limit
        MOV     [ESP+6],AX
        LGDT    [ESP+6]
        RET
  1. 这里本质上涉及到 GDTR 寄存器的使用方式, 知道了他的使用方式就可以理解这段汇编代码的意思了
  2. GDTR 寄存器是 48bit 的, 他不能直接使用mov 操作, 如果需要对他进行赋值, 可以指定一个内存地址, 然后从这个地址中读取 6 个字节(48bit), 赋值给 GDTR 寄存器, 使用 LGDT 指令。
  3. 该寄存器低 16 bit (即 内存的最初的 2 个字节)为 段上限, 它等于 “GDT 的有效字节数 - 1”。剩下的高32 bit (剩余 4 个字节), 代表GDT 的开始地址。
  4. 由于我们的平台是 i386 平台, 所以采用的是小端字节序 http://blog.csdn.net/sky453589103/article/details/50595287

4.2 set_segmdesc

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) & 0x0f) | ((ar >> 8) & 0xf0);
    sd->base_high    = (base >> 24) & 0xff;
    return;
}
  1. 这段代码实际上是用来设置 gdt 表的
  2. 我们首先来看一下 i386 平台中对 段寄存器的定义 http://blog.csdn.net/zhyh1435589631/article/details/50989569

  3. 由于历史遗留因素, base 地址 和 limit 字段被拆成了多个部分, limit字段 高位是段属性的设置

5. 初始化 PIC

  1. PIC 亦即 可编程中断控制器
    这里写图片描述
  2. init_pic

    void init_pic(void)
    /* PICの初期化 */
    {
        io_out8(PIC0_IMR,  0xff  ); /* 全ての割り込みを受け付けない */
        io_out8(PIC1_IMR,  0xff  ); /* 全ての割り込みを受け付けない */
    
        io_out8(PIC0_ICW1, 0x11  ); /* エッジトリガモード */
        io_out8(PIC0_ICW2, 0x20  ); /* IRQ0-7は、INT20-27で受ける */
        io_out8(PIC0_ICW3, 1 << 2); /* PIC1はIRQ2にて接続 */
        io_out8(PIC0_ICW4, 0x01  ); /* ノンバッファモード */
    
        io_out8(PIC1_ICW1, 0x11  ); /* エッジトリガモード */
        io_out8(PIC1_ICW2, 0x28  ); /* IRQ8-15は、INT28-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;
    }
  3. 其中 IMR 是 中断屏蔽寄存器, ICW 是初始化控制数据, ICW3 设定主从连接(确定是使用哪个IRQ 来通知CPU), ICW2 确定 使用哪一号中断。

6. 中断处理程序制作

  1. 首先编写 中断处理程序, 然后将程序注册到 IDT 表中, 即可
  2. 需要注意的是这里 鼠标使用 IRQ12, 键盘使用 IRQ1
  3. 相应调用代码:
void HariMain(void)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
    char s[40], mcursor[256];
    int mx, my;

    init_gdtidt();
    init_pic();
    io_sti(); /* IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 */

    init_palette();
    init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
    mx = (binfo->scrnx - 16) / 2; /* 画面中央になるように座標計算 */
    my = (binfo->scrny - 28 - 16) / 2;
    init_mouse_cursor8(mcursor, COL8_008484);
    putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
    sprintf(s, "(%d, %d)", mx, my);
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);

    io_out8(PIC0_IMR, 0xf9); /* PIC1とキーボードを許可(11111001) */
    io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */

    for (;;) {
        io_hlt();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值