1.界面
上文中我將一些信息保存到0x0ff0地址,這些信息有8bit的screen mode,屏幕高與寬,以及顯示用內存地址,現在我們將這些信息保存到struct裏:
struct BOOTINFO {
char cyls, leds, vmode, reserve;
short scrnx, scrny;
char *vram;
};
struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
8bit顯示模式只有16色,既0-15,如果你不想使用系統默認的16色,可以自定義喜歡的16種顏色。定義方式爲:
void set_palette()
{
int i, eflags;
eflags = io_load_eflags(); /*記錄eflags*/
io_cli(); /*禁止中斷*/
io_out8(0x
/*begin,開始定義顏色*/
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
/*end*/
io_store_eflags(eflags); /*恢復EFLAGS*/
return;
}
下面就可以繪製界面了,一個方形繪製方法如下:
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
int x, y;
for (y = y0; y <= y1; y++) {
for (x = x0; x <= x1; x++)
vram[y * xsize + x] = c;
}
return;
}
unsigned char *vram爲顯示內存地址
int xsize爲屏幕的寬既320
unsigned char c爲顏色
int x0, int y0爲方形左上角點
int x1, int y1爲方形右下角點
2.字體
編寫一個新C源文件,爲font.c。定義一個符號方法如下:
void char_0(char *font)
{
font[0]=0x00;
font[1]=0x18;
font[2]=0x24;
font[3]=0x24;
font[4]=0x42;
font[5]=0x42;
font[6]=0x42;
font[7]=0x42;
font[8]=0x42;
font[9]=0x42;
font[10]=0x42;
font[11]=0x24;
font[12]=0x24;
font[13]=0x18;
font[14]=0x00;
font[15]=0x00;
}
char *font爲內存地址,1個文字長寬爲8bit,高爲16bit。以上函數是定義數字0。
符號顯示方法如下:
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
int i;
char *p, d /* data */;
for (i = 0; i < 16; i++) {
p = vram + (y + i) * xsize + x;
d = font[i];
if ((d & 0x80) != 0) { p[0] = c; }
if ((d & 0x40) != 0) { p[1] = c; }
if ((d & 0x20) != 0) { p[2] = c; }
if ((d & 0x10) != 0) { p[3] = c; }
if ((d & 0x08) != 0) { p[4] = c; }
if ((d & 0x04) != 0) { p[5] = c; }
if ((d & 0x02) != 0) { p[6] = c; }
if ((d & 0x01) != 0) { p[7] = c; }
}
return;
}
3.bootpack.c的完整源代碼
/*Colimas Simple OS*/
#include "font.h"
void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);
void init_palette(void);
void set_palette(void);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
void init_screen(char *vram, int x, int y);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
void drawchar(char *vram, int xsize, int x, int y, char c, unsigned char s);
void drawstring(char *vram, int xsize, int x, int y, char c, unsigned char *s);
#define COL8_000000 0
#define COL8_FF0000 1
#define COL8_00FF00 2
#define COL8_FFFF00 3
#define COL8_0000FF 4
#define COL8_FF00FF 5
#define COL8_00FFFF 6
#define COL8_FFFFFF 7
#define COL8_C
#define COL8_840000 9
#define COL8_008400 10
#define COL8_848400 11
#define COL8_000084 12
#define COL8_840084 13
#define COL8_008484 14
#define COL8_848484 15
//entry
struct BOOTINFO {
char cyls, leds, vmode, reserve;
short scrnx, scrny;
char *vram;
};
void ColimasMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
init_palette();
init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
//drawstring(binfo->vram, binfo->scrnx, 18, 10, COL8_FFFFFF, s);
drawchar(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, 'C');
drawchar(binfo->vram, binfo->scrnx, 18, 10, COL8_FFFFFF, 'I');
drawchar(binfo->vram, binfo->scrnx, 26, 10, COL8_FFFFFF, 'A');
for (;;) {
io_hlt();
}
}
void init_palette(void)
{
set_palette();
return;
}
void set_palette()
{
int i, eflags;
eflags = io_load_eflags();
io_cli();
io_out8(0x
/*begin*/
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
io_out8(0x
/*end*/
io_store_eflags(eflags);
return;
}
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
int x, y;
for (y = y0; y <= y1; y++) {
for (x = x0; x <= x1; x++)
vram[y * xsize + x] = c;
}
return;
}
void init_screen(char *vram, int x, int y)
{
boxfill8(vram, x, COL8_0000FF, 0, 0, x - 1, y - 29);
boxfill8(vram, x, COL8_C
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
boxfill8(vram, x, COL8_C
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
return;
}
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
int i;
char *p, d /* data */;
for (i = 0; i < 16; i++) {
p = vram + (y + i) * xsize + x;
d = font[i];
if ((d & 0x80) != 0) { p[0] = c; }
if ((d & 0x40) != 0) { p[1] = c; }
if ((d & 0x20) != 0) { p[2] = c; }
if ((d & 0x10) != 0) { p[3] = c; }
if ((d & 0x08) != 0) { p[4] = c; }
if ((d & 0x04) != 0) { p[5] = c; }
if ((d & 0x02) != 0) { p[6] = c; }
if ((d & 0x01) != 0) { p[7] = c; }
}
return;
}
void drawchar(char *vram, int xsize, int x, int y, char c, unsigned char s)
{
char *font;
get_char(font,s);
putfont8(vram, xsize, x, y, c,font);
return;
}
4.顯示結果如下:
5.問題
你一定很奇怪我爲什麼沒有使用字符串和數組。字符串和數組編譯後屬於.data segement。我使用objcopy,將obj文件轉換爲binary文件後,我的程序不能正確地找到這些.data segement的地址。我現在正在嘗試自己編寫連接器。