《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 Files\Oracle\VirtualBox\VirtualBox.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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM