暑假果然是滋生懶散的溫床. (╯‵□′)╯︵┻━┻
好久不動都忘記之前做到哪里了, 上次好像做到了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 }
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 }
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
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
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.