话说之前在学习单片机的时候学习到了很多关于处理硬件结构,存储单元的知识。我想后面有空开个专门把8086CPU和单片机的CPU按照寄存器啊,结构啊的分类标准比较下。总之比较下总结下思路就会清晰很多。
OK,我们开始。之前的内容还是要大概看些做了哪些事情的:之前我们了解了软盘的结构,然后我知道了磁盘的存储方式。紧接着学习了怎么调用BIOS函数,如何在C语言中调用汇编指令。如何将C语言的文件生成.sys。
要想在屏幕上面显示什么的话只要往VRAM里面写入一些东西就好了。但是在C语言中是没有办法直接向内存地址写入语句的,也就是没办法直接用DB指令。(好吧,其实是有的)。于是我们就可以创建这个功能的函数。
解释:1、ECX,当然,因为已经变成了32位的模式的话自然就ECX寄存器了。ESP是啥玩意来着。我查下:哦哦哦~是SP的加强版的含义吧,Extended Stack Pointer。是用于堆栈的指针寄存器。[ESP+4]存放的是地址。[ESP+8]存放的是数据。自然加上[]就意识到之前讲到的是存储单元的额内容。他们分别放在ECX和AL这个2个地方,然后要将AL的数据放到ECX的空里面去。
如果C语言要用那个函数的话,直接用_write_mem8就可以了。其中每一个数组存放内存的地址要在之前的基础上+4.也就是[ESP+4][ESP+8][ESP+12][ESP+16]等等。
[INSTRSET "i486p"]这句的含义就是这个程序可以给486用,CPU的谱系图就是8086~80186~286~386~486~Pentium下去。其中386之后的处理器都是32位的,包括386.
但是为什么是白色?因为之前的程序部分里调用的时候写的是write_mem8(i, 15); /* MOV BYTE [i],15 */,15是15种颜色,就是白色。
之前的认为定义的一个函数然后写进内存的语句可以被代替。代替的方法是使用 * i = i & 0x0f ;但是这里有个数据类型的错误问题,因为编译器不知道这里的数据到底是Byte 还是 word 还是 dword。
解决办法:
char *p ; /*变量P是指定内存地址的专用变量,positon嘛~ */
然后写 * p = i & 0x0f 就可以了,因为编译器认为P是地址专用变量,用于存放字符的,所以就是byte。OK~那么word和dword 呢~咋办?
char *p是byte
short *p 是word
int * p是dword
他们都是4字节的,那么1字节的就是 char i; short i;就是2字节的。int i;是4字节的。
然后坐着用这个语句就代替了之前的调用汇编的那个函数。实现了一样的结果。
cast的含义原本是将XXX压入模具,然后计算机语言中是类型转换。
指针式表示内存地址的数值,当然,在汇编中是用的内存地址,而在C语言中是指针。
因为C在设计的时候是认为的普通数值和指针数值是2种不同的数值,于是如果在C中要是不先转换类型就使用的话就会出现警告。那么如何解决这个问题呢:
p = (char *) i;就是实现了数据类型的转换,之前char *很眼熟。将数值变成了表示内存地址的整数。
因为上面讲了指针,然后作者就将原来的程序中改写了一句话, for (i = 0xa0000; i <= 0xaffff; i++) {
write_mem8(i, 15);改为
*(p + i) = i & 0x0f ;
这里就体现了指针的简洁。短小精悍。
*(p + i) 可以用p[i]代替。
下面就是颜色的问题了。
要想绘制一个操作系统模样的画面,只要有16种颜色就足够了。然后又很多的编号,这些编号要在bootback.c中标出来。
下面就是开始对init_palette进行解释。
这部分都讲的一些简单的内容,就不做笔记了。
哟~下面讲了中断,但是作者不打算细讲,马上我加个单片机中断的总结。
void HariMain(void)
{
int i; /* 曄悢愰尵丅i偲偄偆曄悢偼丄32價僢僩偺惍悢宆 */
char *p; /* p偲偄偆曄悢偼丄BYTE [...]梡偺斣抧 */
init_palette(); /* 僷儗僢僩傪愝掕 */
p = (char *) 0xa0000; /* 斣抧傪戙擖 */
for (i = 0; i <= 0xffff; i++) {
p[i] = i & 0x0f;
}
for (;;) {
io_hlt();
}
}
这里显示的main函数的要注意的就是调用调色板。
颜色OK了下面就开始弄形状了。
VRAM的的地址计算有个公式。320X200像素的。
0xa0000+x+y+320
地址知道了,再加上之前学的写进颜色的话就可以显示自己想要的画面了。
绘制矩形的程序也很简单,贴上代码:
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(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
#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_C6C6C6 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
void HariMain(void)
{
char *p; /* p偲偄偆曄悢偼丄BYTE [...]梡偺斣抧 */
init_palette(); /* 僷儗僢僩傪愝掕 */
p = (char *) 0xa0000; /* 斣抧傪戙擖 */
boxfill8(p, 320, COL8_FF0000, 20, 20, 120, 120);
boxfill8(p, 320, COL8_00FF00, 70, 50, 170, 150);
boxfill8(p, 320, COL8_0000FF, 120, 80, 220, 180);
for (;;) {
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00, /* 0:崟 */
0xff, 0x00, 0x00, /* 1:柧傞偄愒 */
0x00, 0xff, 0x00, /* 2:柧傞偄椢 */
0xff, 0xff, 0x00, /* 3:柧傞偄墿怓 */
0x00, 0x00, 0xff, /* 4:柧傞偄惵 */
0xff, 0x00, 0xff, /* 5:柧傞偄巼 */
0x00, 0xff, 0xff, /* 6:柧傞偄悈怓 */
0xff, 0xff, 0xff, /* 7:敀 */
0xc6, 0xc6, 0xc6, /* 8:柧傞偄奃怓 */
0x84, 0x00, 0x00, /* 9:埫偄愒 */
0x00, 0x84, 0x00, /* 10:埫偄椢 */
0x84, 0x84, 0x00, /* 11:埫偄墿怓 */
0x00, 0x00, 0x84, /* 12:埫偄惵 */
0x84, 0x00, 0x84, /* 13:埫偄巼 */
0x00, 0x84, 0x84, /* 14:埫偄悈怓 */
0x84, 0x84, 0x84 /* 15:埫偄奃怓 */
};
set_palette(0, 15, table_rgb);
return;
/* static char 柦椷偼丄僨乕僞偵偟偐巊偊側偄偗偳DB柦椷憡摉 */
}
void set_palette(int start, int end, unsigned char *rgb)
{
int i, eflags;
eflags = io_load_eflags(); /* 妱傝崬傒嫋壜僼儔僌偺抣傪婰榐偡傞 */
io_cli(); /* 嫋壜僼儔僌傪0偵偟偰妱傝崬傒嬛巭偵偡傞 */
io_out8(0x03c8, start);
for (i = start; i <= end; i++) {
io_out8(0x03c9, rgb[0] / 4);
io_out8(0x03c9, rgb[1] / 4);
io_out8(0x03c9, rgb[2] / 4);
rgb += 3;
}
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;
}
这样就可以显示3个矩形了。
这玩意不过也就是认为一个一个定义像素点然后显示想显示的东西而已。
这一小节完成。
看看下一个:
结构体、文字显示、GDT/IDT初始化。
加油搞,慢慢慢慢把这一个蓝图填满。