4 显示字符(harib02d)
内部的处理差不多了,我们还是将重点放回到外部显示上来吧。到昨天为止,我们算是画出了一幅稍微像样的画,今天就来在画面上写字。以前我们显示字符主要靠调用BIOS函数,但这次是32位模式,不能再依赖BIOS了,只能自力更生。
那么怎么显示字符呢?字符可以用8×16的长方形像素点阵来表示。想象一个下图左边的数据,然后按下图右边所示的方法置换成0和1,这个方法好像不错。然后根据这些数据在画面上打上点就肯定能显示出字符了。8“位”是一个字节,而1个字符是16个字节。
大家可能会有各种想法,比如“我觉得8×16的字太小了,想显示得更大一些”、“还是小点儿的字好”等。不过刚开始我们就先这样吧,一上来要求太多的话,就没有办法往前进展了。
■■■■■
像这种描画文字形状的数据称为字体(font)数据,那这种字体数据是怎样写到程序里的呢?有一种临时方案:
static char font_A[16] = { 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00 };
其实这仅仅是将刚才的0和1的排列,重写成十六进制数而已。C语言无法用二进制数记录数据,只能写成十六进制或八进制。嗯,读起来真费劲呀。嫌字体不好看,想手动修正一下,都不知道到底需要修改哪儿。但是暂时就先这样吧,以后再考虑这个问题。
数据齐备之后,只要描画到画面上就可以了。用for语句将画8个像素的程序循环16遍,就可以显示出一个字符了。于是我们制作了下面这个函数。
void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char d; /* data */ for (i = 0; i < 16; i++) { d = font[i]; if ((d & 0x80) ! = 0) { vram[(y + i) * xsize + x + 0] = c; } if ((d & 0x40) ! = 0) { vram[(y + i) * xsize + x + 1] = c; } if ((d & 0x20) ! = 0) { vram[(y + i) * xsize + x + 2] = c; } if ((d & 0x10) ! = 0) { vram[(y + i) * xsize + x + 3] = c; } if ((d & 0x08) ! = 0) { vram[(y + i) * xsize + x + 4] = c; } if ((d & 0x04) ! = 0) { vram[(y + i) * xsize + x + 5] = c; } if ((d & 0x02) ! = 0) { vram[(y + i) * xsize + x + 6] = c; } if ((d & 0x01) ! = 0) { vram[(y + i) * xsize + x + 7] = c; } } return; }
if语句是第一次登场,我们来介绍一下。if语句先检查“()”内的条件式,当条件成立时,就执行“{}”内的语句,条件不成立时,什么都不做。
&是以前曾出现过的AND(“与”)运算符。0x80也就是二进制数10000000,它与d进行“与”运算的结果如果是0,就说明d的最左边一位是0。反之,如果结果不是0,则d的最左边一位就是1。“! =”是不等于的意思,在其他语言中,有时写作“<>”。
■■■■■
虽然这样也能显示出“A”来,但还是把程序稍微整理一下比较好,因为现在的程序又长运行速度又慢。
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; }
这样就好多了,我们就用这段程序吧。
下面将这段程序嵌入到bootpack.c中进行整理。大家仔细看看,如果顺利的话,能显示出字符“A”。紧张激动的时刻到了,运行“make run”。哦,“A”显示出来了!