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 03c 8, 0); /*向0x 03c 8端口发送命令*/
/*begin,开始定义颜色*/
io_out8(0x 03c 9, 0x00 / 4); /*R*/
io_out8(0x 03c 9, 0x00 / 4); /*G*/
io_out8(0x 03c 9, 0x00 / 4); /*B*/
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff/ 4);
io_out8(0x 03c 9, 0xff/ 4);
io_out8(0x 03c 9, 0x00/ 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
/*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 6C 6C 6 8
#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 03c 8, 0);
/*begin*/
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff/ 4);
io_out8(0x 03c 9, 0xff/ 4);
io_out8(0x 03c 9, 0x00/ 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xff / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0xc6 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x00 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
io_out8(0x 03c 9, 0x84 / 4);
/*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 6C 6C 6, 0, y - 28, x - 1, y - 28);
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
boxfill8(vram, x, COL8_C 6C 6C 6, 0, y - 26, x - 1, y - 1);
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的地址。我现在正在尝试自己编写连接器。