• 《30天自制操作系统》读书笔记(4) 绘图


    暑假果然是滋生懒散的温床. (╯‵□′)╯︵┻━┻

    好久不动都忘记之前做到哪里了, 上次好像做到了C语言的引入, 这一节所做的东西都相当轻松, 将会绘制出操作系统的基本界面.

    • 绘图的原理

      按照书中所说, 将值写入到显存中就能在屏幕上显示相应的像素, 在asmhead.nas 中有这一段:

     1 CYLS    EQU    0x0ff0    ; 设定启动区    
     2 LEDS    EQU    0x0ff1    
     3 VMODE    EQU    0x0ff2    ; 关于颜色数目的信息,颜色的位数    
     4 SCRNX    EQU    0x0ff4    ; 分辨率 X(Screen X)    
     5 SCRNY    EQU    0x0ff6    ; 分辨率 Y(Screen Y)    
     6 VRAM    EQU    0x0ff8    ; 图像缓冲区的起始地址    
     7 
     8     ORG    0xc200        
     9 
    10 
    11 
    12     MOV    AL,0x13    ; VGA 显卡    
    13     MOV    AH,0x00
    14     INT    0x10
    15     MOV    BYTE [VMODE],8    ; 记录画面模式    
    16     MOV    WORD [SCRNX],320
    17     MOV    WORD [SCRNY],200
    18     MOV    DWORD [VRAM],0x000a0000

    调用十号中断来指定显卡模式, 后面的几个MOV指令用来储存和显示有关的关键信息(为什么不直接用常量呢?), 在bootpack.c中有

    1 struct BOOTINFO { /* 0x0ff0-0x0fff */
    2     char cyls; /* 启动区读硬盘读到何处为止 */
    3     char leds; /* 启动时LED的状态*/
    4     char vmode; /* 显卡模式*/
    5     char reserve;
    6     short scrnx, scrny; /* 分辨率*/
    7     char *vram;
    8 };

    这里就将结构体指针指向了这些信息, 可以知道VRAM的地址是0xa0000想指定地址写入数据, 当然是用指针, 将VRAM声明为一个数组即可.

    作者顺便指出了数组的操作array[index] 仅是一个语法糖, a[i] 等价于*(a + i), 当然也等价于*(i + a), 所以很神奇的, a[i] 和 i[a] 在C语言里是等效的.

    • 设定调色板

      作者替我们指定了300x200 8位的颜色模式, 如何将 0xffffff 的颜色值映射0~0xfff的空间里? 一一对应显然是不可能的, 事实上8位色彩模式中, 0到0xfff这255中颜色是由我们自己指定的, 譬如说0可以对应红色0xff0000, 这种对应关系显然被储存起来, 这就是调色板(palette),作者给出了16中颜色的对应关系, 其中14号色被我改了, 调色板的数据结构如下(就一个unsigned char数组):

     1     static unsigned char table_rgb[16 * 3] =
     2            {
     3         0x00, 0x00, 0x00,    /*  0:黑色*/
     4         0xff, 0x00, 0x00,    /*  1:亮红*/
     5         0x00, 0xff, 0x00,    /*  2:亮绿*/
     6         0xff, 0xff, 0x00,    /*  3:亮黄*/
     7         0x00, 0x00, 0xff,    /*  4:亮蓝*/
     8         0xff, 0x00, 0xff,    /*  5:亮紫*/
     9         0x00, 0xff, 0xff,    /*  6:浅亮蓝*/
    10         0xff, 0xff, 0xff,    /*  7:白色*/
    11         0xc6, 0xc6, 0xc6,    /*  8:亮灰*/
    12         0x84, 0x00, 0x00,    /*  9:暗红*/
    13         0x00, 0x84, 0x00,    /* 10:暗绿*/
    14         0x84, 0x84, 0x00,    /* 11:暗黄*/
    15         0x00, 0x00, 0x84,    /* 12:暗青*/
    16         0x84, 0x00, 0x84,    /* 13:暗紫*/
    17         0x5b, 0x9b, 0xd5,    /* 14:浅灰蓝5B,9B,D5*/
    18         0x84, 0x84, 0x84    /* 15:暗灰*/
    19     };

    如何让我们设置调色板生效? 作者给出了如下步骤:

      这里的0x03c9 是设备端口号, 屏蔽和恢复中断使用CLI和STI两个指令, 在naskfunc.nas里面封装成了函数io_cli(); 和 io_stl(), CLI(Clear interrupt flag) 将中断标志(interrupt flag)置零, STI(Set interrupt flag)则是将中断标志置一. 设置调色板的时候需要屏蔽中断, 但不知道当前的状态是什么, 所以在CLI之前要保存中断标志的状态. 中断标志保存在32位寄存器EFLAGS上, 由16位的FLAGS扩展而来, 下图应该是FLAGS 的示意图:中断标志位于第9位. 0 位是进位标志, 2是奇偶标志, 4 是辅助进位标志, 6是零标志, 7是符号标志, 8,10额…忘了, 11是溢出标志…使用指令PUSHFD和POPFD储存和恢复整个EFLAGS的状态, 封装为io_load_eflags()函数和io_store_eflags(eflags)函数.

    对端口的读写要使用IN 指令和 OUT指令, 注意这里的IN是读取而OUT是写入.

    结合以上的知识, 设置调色板的函数如下:

     1 void set_palette(int start, int end, unsigned char *rgb)
     2 {
     3     int i, eflags;
     4     eflags = io_load_eflags();    /*记录中断标志的值 */
     5     io_cli();                     /*禁止中断 */
     6     io_out8(0x03c8, start);
     7     for (i = start; i <= end; i++)
     8            {
     9         io_out8(0x03c9, rgb[0] / 4);    
    10         io_out8(0x03c9, rgb[1] / 4);
    11         io_out8(0x03c9, rgb[2] / 4);
    12         rgb += 3;
    13     }
    14     io_store_eflags(eflags);    /* 恢复中断标志*/
    15     return;
    16 }

    有个疑惑便是rgb[0] 为什么要除以四再写入, 如果去掉这一句颜色会变得很灰…有谁知道的还望告知…(/4不就是往左移动两位?)

    • 绘制界面

      我们写了一个叫做boxfill8的函数用来绘制矩形, 并用它来构建我们的基本界面:

    二维屏幕和一维的地址换算关系如下: addr = 0xa0000 + x + y * 320

    void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);

    参数的意思分别是: 显存地址, 换算参数(屏幕宽度), 颜色, 矩形的四个点.

    使用以下的代码画出界面:

     1 void init_screen8(char *vram, int x, int y)
     2 {
     3     boxfill8(vram, x, COL8_008484,  0, 0,          x -  1, y - 29);    //绘制桌面填充灰蓝色
     4     boxfill8(vram, x, COL8_C6C6C6,  0, y - 28, x -  1, y - 28);    //第一条阴影
     5     boxfill8(vram, x, COL8_FFFFFF,  0, y - 27, x -  1, y - 27);    //绘制第二条阴影
     6     boxfill8(vram, x, COL8_C6C6C6,  0, y - 26, x -  1, y -  1);    //绘制任务栏主体
     7 
     8     boxfill8(vram, x, COL8_FFFFFF,  3, y - 24, 59, y - 24);        //绘制"开始"按钮 周围六条直线 
     9     boxfill8(vram, x, COL8_FFFFFF,  2, y - 24,  2, y -  4);
    10     boxfill8(vram, x, COL8_848484,  3, y -  4, 59, y -  4);
    11     boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y -  5);
    12     boxfill8(vram, x, COL8_000000,  2, y -  3, 59, y -  3);
    13     boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y -  3);
    14 
    15     boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);//绘制状态栏 四条直线 
    16     boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
    17     boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
    18     boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
    19     return;
    20 }

    得到的界面如下:

    屏幕下方左右两个"按钮"放大看:

    其实就是在原来的底色上画多了几条直线, 左边的是6条, 右边的是4条.

    看情况, 这将会是我们的操作系统的桌面.

     

    • 显示字符

      使用了asmhead.nas 后我们进入了32位模式(似乎是保护模式), 不可以使用int 0x13中断了, 因此要显示字符只能自己画.

    作者使用8x16 的矩阵来表示一个字符, 不知道真正的字体文件*.ttf是否用这样的方式储存…

    换算成16进制是:

    这样的表示方法难以调整, 所以作者使用了一个文本文档来描画字体, 在这个文本文档里面8是:

    char 0x38
    ........
    ...**...
    ..*..*..
    .*....*.
    .*....*.
    .*....*.
    ..*..*..
    ...**...
    ..*..*..
    .*....*.
    .*....*.
    .*....*.
    ..*..*..
    ...**...
    ........
    ........

    然后伟大的作者又搬出了自己的"编译器", makefont.exe, (╯‵□′)╯︵┻━┻), 神烦的"别人家的编译器", 这也意味这Makefile又要改动了…如何画出字符和字符串呢?

    写一个很厉害的putfont8函数:

     1 void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
     2 {
     3     int i;
     4     char *p, d /* data */;
     5     for (i = 0; i < 16; i++) {
     6         p = vram + (y + i) * xsize + x;
     7         d = font[i];
     8         if ((d & 0x80) != 0) { p[0] = c; }
     9         if ((d & 0x40) != 0) { p[1] = c; }
    10         if ((d & 0x20) != 0) { p[2] = c; }
    11         if ((d & 0x10) != 0) { p[3] = c; }
    12         if ((d & 0x08) != 0) { p[4] = c; }
    13         if ((d & 0x04) != 0) { p[5] = c; }
    14         if ((d & 0x02) != 0) { p[6] = c; }
    15         if ((d & 0x01) != 0) { p[7] = c; }
    16     }
    17     return;
    18 }

    让特地的数和字体数据相与,判断特定位是否为1, 很厉害的做法.

    显示字符串的函数:

    1 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
    2 {
    3     extern char hankaku[4096];
    4     for (; *s != 0x00; s++) {
    5         putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
    6         x += 8;
    7     }
    8     return;
    9 }

    在主函数里调用

    1 putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, "ABC 123");
    2 putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "OS.");
    3 putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "OS."); 

    结果如下:

    • 显示变量值

    为了显示变量值, 作者使用了名为GO的编译器里的sprintf函数,(这货是GO语言的GO吗?), Sprintf函数就是将指定内容格式化输出到字符流中, 然后我们再将这个字符显示出来, 达到显示变量内容的目的.

    添加头文件stdio.h, 主函数加入以下语句:

    1     int mx = (binfo->scrnx - 16) / 2;        //水平居中
    2     int my = (binfo->scrny - 28 - 16) / 2;    //排除任务栏垂直居中
    3     sprintf(s, "(%d, %d)", mx, my);
    4     putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); 

    效果如下:

    • 显示鼠标指针

      鼠标的显示和字符大同小异, 但是这里使用字符来储存而不是二进制, 因为需要填充色, 边缘色和背景色…作者画的鼠标实在难看, 我用的是@BIT_祝威 写好的鼠标, 特此感谢!

     1 /* 16*16 Mouse */
     2     static char cursor[16][16] = {
     3         "*...............",
     4         "**..............",
     5         "*O*.............",
     6         "*OO*............",
     7         "*OOO*...........",
     8         "*OOOO*..........",
     9         "*OOOOO*.........",
    10         "*OOOOOO*........",
    11         "*OOOOOOO*.......",
    12         "*OOOO*****......",
    13         "*OO*O*..........",
    14         "*O*.*O*.........",
    15         "**..*O*.........",
    16         "*....*O*........",
    17         ".....*O*........",
    18         "......*........."
    19     };

     事前将上面的图案处理成颜色信息cursor[], 再使用putblock8_8函数将鼠标画出来, 效果如下:

     这次就做到这里…按书中的指示将代码分装成几个文件, 下面是当前改动的代码:

     这次的大部分代码在graphic.c

      1 #include "bootpack.h"
      2 
      3 void init_palette(void)
      4 {
      5     static unsigned char table_rgb[16 * 3] =
      6            {
      7         0x00, 0x00, 0x00,    /*  0:黑色*/
      8         0xff, 0x00, 0x00,    /*  1:亮红*/
      9         0x00, 0xff, 0x00,    /*  2:亮绿*/
     10         0xff, 0xff, 0x00,    /*  3:亮黄*/
     11         0x00, 0x00, 0xff,    /*  4:亮蓝*/
     12         0xff, 0x00, 0xff,    /*  5:亮紫*/
     13         0x00, 0xff, 0xff,    /*  6:浅亮蓝*/
     14         0xff, 0xff, 0xff,    /*  7:白色*/
     15         0xc6, 0xc6, 0xc6,    /*  8:亮灰*/
     16         0x84, 0x00, 0x00,    /*  9:暗红*/
     17         0x00, 0x84, 0x00,    /* 10:暗绿*/
     18         0x84, 0x84, 0x00,    /* 11:暗黄*/
     19         0x00, 0x00, 0x84,    /* 12:暗青*/
     20         0x84, 0x00, 0x84,    /* 13:暗紫*/
     21         0x5b, 0x9b, 0xd5,    /* 14:浅灰蓝5B,9B,D5*/
     22         0x84, 0x84, 0x84    /* 15:暗灰*/
     23     };
     24     set_palette(0, 15, table_rgb);
     25     return;
     26 
     27     /* static char,储存数据, 相当于DB*/ 
     28 }
     29 
     30 void set_palette(int start, int end, unsigned char *rgb)
     31 {
     32     int i, eflags;
     33     eflags = io_load_eflags();    /*记录中断标志的值 */
     34     io_cli();                     /*禁止中断 */
     35     io_out8(0x03c8, start);
     36     for (i = start; i <= end; i++)
     37            {
     38         io_out8(0x03c9, rgb[0] / 4);    
     39         io_out8(0x03c9, rgb[1] / 4);
     40         io_out8(0x03c9, rgb[2] / 4);
     41         rgb += 3;
     42     }
     43     io_store_eflags(eflags);    /* 恢复中断标志*/
     44     return;
     45 }
     46 
     47 void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
     48 {
     49     int x, y;
     50     for (y = y0; y <= y1; y++) {
     51         for (x = x0; x <= x1; x++)
     52             vram[y * xsize + x] = c;
     53     }
     54     return;
     55 }
     56 
     57 void init_screen8(char *vram, int x, int y)
     58 {
     59     boxfill8(vram, x, COL8_008484,  0, 0,          x -  1, y - 29);    //绘制桌面填充灰蓝色
     60     boxfill8(vram, x, COL8_C6C6C6,  0, y - 28, x -  1, y - 28);    //第一条阴影
     61     boxfill8(vram, x, COL8_FFFFFF,  0, y - 27, x -  1, y - 27);    //绘制第二条阴影
     62     boxfill8(vram, x, COL8_C6C6C6,  0, y - 26, x -  1, y -  1);    //绘制任务栏主体
     63 
     64     boxfill8(vram, x, COL8_FFFFFF,  3, y - 24, 59, y - 24);        //绘制"开始"按钮 周围六条直线 
     65     boxfill8(vram, x, COL8_FFFFFF,  2, y - 24,  2, y -  4);
     66     boxfill8(vram, x, COL8_848484,  3, y -  4, 59, y -  4);
     67     boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y -  5);
     68     boxfill8(vram, x, COL8_000000,  2, y -  3, 59, y -  3);
     69     boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y -  3);
     70 
     71     boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);//绘制状态栏 四条直线 
     72     boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
     73     boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
     74     boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
     75     return;
     76 }
     77 
     78 void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
     79 {
     80     int i;
     81     char *p, d /* data */;
     82     for (i = 0; i < 16; i++) {
     83         p = vram + (y + i) * xsize + x;
     84         d = font[i];
     85         if ((d & 0x80) != 0) { p[0] = c; }
     86         if ((d & 0x40) != 0) { p[1] = c; }
     87         if ((d & 0x20) != 0) { p[2] = c; }
     88         if ((d & 0x10) != 0) { p[3] = c; }
     89         if ((d & 0x08) != 0) { p[4] = c; }
     90         if ((d & 0x04) != 0) { p[5] = c; }
     91         if ((d & 0x02) != 0) { p[6] = c; }
     92         if ((d & 0x01) != 0) { p[7] = c; }
     93     }
     94     return;
     95 }
     96 
     97 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
     98 {
     99     extern char hankaku[4096];
    100     for (; *s != 0x00; s++) {
    101         putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
    102         x += 8;
    103     }
    104     return;
    105 }
    106 
    107 void init_mouse_cursor8(char *mouse, char bc)
    108 /* 16*16 Mouse */
    109 {
    110     static char cursor[16][16] = {
    111         "*...............",
    112         "**..............",
    113         "*O*.............",
    114         "*OO*............",
    115         "*OOO*...........",
    116         "*OOOO*..........",
    117         "*OOOOO*.........",
    118         "*OOOOOO*........",
    119         "*OOOOOOO*.......",
    120         "*OOOO*****......",
    121         "*OO*O*..........",
    122         "*O*.*O*.........",
    123         "**..*O*.........",
    124         "*....*O*........",
    125         ".....*O*........",
    126         "......*........."
    127     };
    128     int x, y;
    129 
    130     for (y = 0; y < 16; y++) {
    131         for (x = 0; x < 16; x++) {
    132             if (cursor[y][x] == '*') {
    133                 mouse[y * 16 + x] = COL8_000000;
    134             }
    135             if (cursor[y][x] == 'O') {
    136                 mouse[y * 16 + x] = COL8_FFFFFF;
    137             }
    138             if (cursor[y][x] == '.') {
    139                 mouse[y * 16 + x] = bc;
    140             }
    141         }
    142     }
    143     return;
    144 }
    145 
    146 void putblock8_8(char *vram, int vxsize, int pxsize,
    147     int pysize, int px0, int py0, char *buf, int bxsize)
    148 {
    149     int x, y;
    150     for (y = 0; y < pysize; y++) {
    151         for (x = 0; x < pxsize; x++) {
    152             vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
    153         }
    154     }
    155     return;
    156 }
    View Code

    bootpack.c

     1 #include <stdio.h>
     2 #include "bootpack.h"
     3 
     4 void HariMain(void)
     5 {
     6     struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
     7     char s[40], mcursor[256];    
     8     int mx, my;
     9 
    10     init_gdtidt();
    11     init_palette();
    12     init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
    13     mx = (binfo->scrnx - 16) / 2;        //水平居中 
    14     my = (binfo->scrny - 28 - 16) / 2;    //排除任务栏垂直居中
    15     init_mouse_cursor8(mcursor, COL8_008484);
    16     putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
    17     sprintf(s, "(%d, %d)", mx, my);
    18     putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
    19 
    20     for (;;)
    21     {
    22         io_hlt();
    23     }
    24 }
    View Code

    bootpack.h

     1 /* asmhead.nas */
     2 struct BOOTINFO { /* 0x0ff0-0x0fff */
     3     char cyls; /* 启动区读硬盘读到何处为止 */
     4     char leds; /* 启动时LED的状态*/
     5     char vmode; /* 显卡模式*/
     6     char reserve;
     7     short scrnx, scrny; /* 分辨率*/
     8     char *vram;
     9 };
    10 #define ADR_BOOTINFO    0x00000ff0
    11 
    12 /* naskfunc.nas */
    13 void io_hlt(void);
    14 void io_cli(void);
    15 void io_out8(int port, int data);
    16 int io_load_eflags(void);
    17 void io_store_eflags(int eflags);
    18 void load_gdtr(int limit, int addr);
    19 void load_idtr(int limit, int addr);
    20 
    21 /* graphic.c */
    22 void init_palette(void);
    23 void set_palette(int start, int end, unsigned char *rgb);
    24 void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
    25 void init_screen8(char *vram, int x, int y);
    26 void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
    27 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
    28 void init_mouse_cursor8(char *mouse, char bc);
    29 void putblock8_8(char *vram, int vxsize, int pxsize,
    30     int pysize, int px0, int py0, char *buf, int bxsize);
    31 #define COL8_000000        0
    32 #define COL8_FF0000        1
    33 #define COL8_00FF00        2
    34 #define COL8_FFFF00        3
    35 #define COL8_0000FF        4
    36 #define COL8_FF00FF        5
    37 #define COL8_00FFFF        6
    38 #define COL8_FFFFFF        7
    39 #define COL8_C6C6C6        8
    40 #define COL8_840000        9
    41 #define COL8_008400        10
    42 #define COL8_848400        11
    43 #define COL8_000084        12
    44 #define COL8_840084        13
    45 #define COL8_008484        14
    46 #define COL8_848484        15
    47 
    48 /* dsctbl.c */
    49 struct SEGMENT_DESCRIPTOR {
    50     short limit_low, base_low;
    51     char base_mid, access_right;
    52     char limit_high, base_high;
    53 };
    54 struct GATE_DESCRIPTOR {
    55     short offset_low, selector;
    56     char dw_count, access_right;
    57     short offset_high;
    58 };
    59 void init_gdtidt(void);
    60 void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
    61 void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
    62 #define ADR_IDT        0x0026f800
    63 #define LIMIT_IDT    0x000007ff
    64 #define ADR_GDT        0x00270000
    65 #define LIMIT_GDT    0x0000ffff
    66 #define ADR_BOTPAK    0x00280000
    67 #define LIMIT_BOTPAK    0x0007ffff
    68 #define AR_DATA32_RW    0x4092
    69 #define AR_CODE32_ER    0x409a
    View Code

    naskfunc.nas

     1 ;naskfunc
     2 
     3 [FORMAT "WCOFF"]    ; 制作目标文件的模式
     4 [INSTRSET "i486p"]
     5 [BITS 32]        ; 制作32位模式用的机器语言
     6 
     7 
     8 [FILE "naskfunc.nas"]    ; 源文件名信息
     9 
    10             ; 程序中包含的函数名
    11     GLOBAL    _io_hlt, _io_cli, _io_sti, _io_stihlt
    12     GLOBAL    _io_in8,  _io_in16,  _io_in32
    13     GLOBAL    _io_out8, _io_out16, _io_out32
    14     GLOBAL    _io_load_eflags, _io_store_eflags
    15     GLOBAL    _load_gdtr, _load_idtr    
    16 
    17 ; 实际的函数
    18 
    19 [SECTION .text]    ;
    20 
    21 _io_hlt:    
    22     HLT
    23     RET
    24 _io_cli:    ; void io_cli(void);
    25     CLI
    26     RET
    27 
    28 _io_sti:    ; void io_sti(void);
    29     STI
    30     RET
    31 
    32 _io_stihlt:    ; void io_stihlt(void);
    33     STI
    34     HLT
    35     RET
    36 
    37 _io_in8:    ; int io_in8(int port);
    38     MOV    EDX,[ESP+4]    ; port
    39     MOV    EAX,0
    40     IN    AL,DX
    41     RET
    42 
    43 _io_in16:    ; int io_in16(int port);
    44     MOV    EDX,[ESP+4]    ; port
    45     MOV    EAX,0
    46     IN    AX,DX
    47     RET
    48 
    49 _io_in32:    ; int io_in32(int port);
    50     MOV    EDX,[ESP+4]    ; port
    51     IN    EAX,DX
    52     RET
    53 
    54 _io_out8:    ; void io_out8(int port, int data);
    55     MOV    EDX,[ESP+4]    ; port
    56     MOV    AL,[ESP+8]    ; data
    57     OUT    DX,AL
    58     RET
    59 
    60 _io_out16:    ; void io_out16(int port, int data);
    61     MOV    EDX,[ESP+4]    ; port
    62     MOV    EAX,[ESP+8]    ; data
    63     OUT    DX,AX
    64     RET
    65 
    66 _io_out32:    ; void io_out32(int port, int data);
    67     MOV    EDX,[ESP+4]    ; port
    68     MOV    EAX,[ESP+8]    ; data
    69     OUT    DX,EAX
    70     RET
    71 
    72 _io_load_eflags:    ; int io_load_eflags(void);
    73     PUSHFD    ; PUSH EFLAGS 
    74     POP    EAX
    75     RET
    76 
    77 _io_store_eflags:    ; void io_store_eflags(int eflags);
    78     MOV    EAX,[ESP+4]
    79     PUSH    EAX
    80     POPFD    ; POP EFLAGS 
    81     RET
    82 
    83 _load_gdtr:        ; void load_gdtr(int limit, int addr);
    84         MOV    AX,[ESP+4]        ; limit
    85         MOV    [ESP+6],AX
    86         LGDT    [ESP+6]
    87         RET
    88 
    89 _load_idtr:        ; void load_idtr(int limit, int addr);
    90         MOV    AX,[ESP+4]        ; limit
    91         MOV    [ESP+6],AX
    92         LIDT    [ESP+6]
    93         RET
    View Code

    Makefile

     1 OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj
     2 
     3 TOOLPATH = ../z_tools/
     4 INCPATH  = ../z_tools/haribote/
     5 
     6 MAKE     = $(TOOLPATH)make.exe -r
     7 NASK     = $(TOOLPATH)nask.exe
     8 CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
     9 GAS2NASK = $(TOOLPATH)gas2nask.exe -a
    10 OBJ2BIM  = $(TOOLPATH)obj2bim.exe
    11 MAKEFONT = $(TOOLPATH)makefont.exe
    12 BIN2OBJ  = $(TOOLPATH)bin2obj.exe
    13 BIM2HRB  = $(TOOLPATH)bim2hrb.exe
    14 RULEFILE = $(TOOLPATH)haribote/haribote.rul
    15 EDIMG    = $(TOOLPATH)edimg.exe
    16 DEL      = del
    17 SHORTCUT = "D:Program FilesOracleVirtualBoxVirtualBox.exe" --comment "OS1" --startvm "a5c4b0e6-e142-4720-98ee-056911204b29"
    18 
    19 default :
    20     $(MAKE) install
    21     $(MAKE) run
    22     $(MAKE) clean
    23 
    24 ipl10.bin : ipl10.nas Makefile
    25     $(NASK) ipl10.nas ipl10.bin ipl10.lst
    26 
    27 asmhead.bin : asmhead.nas Makefile
    28     $(NASK) asmhead.nas asmhead.bin asmhead.lst
    29 
    30 hankaku.bin : hankaku.txt Makefile
    31     $(MAKEFONT) hankaku.txt hankaku.bin
    32 
    33 hankaku.obj : hankaku.bin Makefile
    34     $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
    35 
    36 bootpack.bim : $(OBJS_BOOTPACK) Makefile
    37     $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map 
    38         $(OBJS_BOOTPACK)
    39 # 3MB+64KB=3136KB
    40 
    41 bootpack.hrb : bootpack.bim Makefile
    42     $(BIM2HRB) bootpack.bim bootpack.hrb 0
    43 
    44 haribote.sys :asmhead.bin bootpack.hrb Makefile
    45     copy /B asmhead.bin+bootpack.hrb haribote.sys
    46 
    47 haribote.img : ipl10.bin haribote.sys Makefile
    48     $(EDIMG)   imgin:../z_tools/fdimg0at.tek 
    49         wbinimg src:ipl10.bin len:512 from:0 to:0 
    50         copy from:haribote.sys to:@: 
    51         imgout:haribote.img
    52 
    53 %.gas : %.c Makefile
    54     $(CC1) -o $*.gas $*.c
    55 
    56 %.nas : %.gas Makefile
    57     $(GAS2NASK) $*.gas $*.nas
    58 
    59 %.obj : %.nas Makefile
    60     $(NASK) $*.nas $*.obj $*.lst
    61 
    62 install:
    63     $(MAKE) haribote.img
    64 
    65 run :
    66     echo Running... 
    67     $(SHORTCUT)
    68     echo Finished
    69 
    70 clean :
    71     -$(DEL) *.bin
    72     -$(DEL) *.lst
    73     -$(DEL) *.gas
    74     -$(DEL) *.obj
    75     -$(DEL) bootpack.nas
    76     -$(DEL) bootpack.map
    77     -$(DEL) bootpack.bim
    78     -$(DEL) bootpack.hrb
    79     -$(DEL) haribote.sys
    80     -$(DEL) *.*~
    81     -$(DEL) *~
    82     echo Cleaned.
    View Code
  • 相关阅读:
    Python 数据处理 正则匹配,清洗脏数据
    Pycharm自用激活码
    编程杂谈 集群与分布式
    win10 向右键添加管理员级CMD
    win10 笔记本键盘永久屏蔽Numlk键
    Golong 环境搭建
    python 各种锁机制归纳整理
    MySQL数据库操作
    Web框架本质
    Django框架
  • 原文地址:https://www.cnblogs.com/lastavengers/p/3895833.html
Copyright © 2020-2023  润新知