随笔 - 3  文章 - 0  评论 - 0  阅读 - 125 

画面显示

笔者小时候吃螃蟹时,尝尝将蟹钳扭下来玩耍,只需抻拉内部的白筋,蟹钳就会自行开合,而不需要我们亲自关闭或打开蟹钳。眼下我们进入了画面显示阶段,我们可以自由地掌握屏幕的每一块像素,但在绘制像素时我们不能直接用水笔在屏幕上勾勒。回忆在进入32位保护模式之前,我们确定了VRAM占据的空间为0xa0000到0xaffff,这些位置恰好对应了我们的像素点。如果修改这一部分内存的值,我们就可以改变屏幕的颜色或画面。
然而,眼下的问题是如何写入内存?一方面,我们可以使用汇编语言来操作内存,另一方面,我们可以直接使用C语言的指针算术来操作内存。

naskfunc.nas中编写新的汇编函数。

[FORMAT "WCOFF"] ; 制作目标文件的格式
[INSTRSET "i486p"] ; 使用到486为止的指令
[BITS 32] ; 制作32位模式对应的机械语言
[FILE "naskfunc.nas"] ; 源文件名
GLOBAL _io_hlt ; 程序中包含的函数名
GLOBAL _write_mem8
[SECTION .text] ; 以下是函数本体
_io_hlt:
HLT
RET
_write_mem8: ; void write_mem8(int addr, int data)
MOV ECX, [ESP+4]
MOV AL, [ESP+8]
MOV [ECX], AL
RET

注意⚠️我们添加了一行[INSTRSET "i486p"],因为在新函数_write_mem8中我们用到了MOV指令,我们必须指具体定是哪一个指令集中的MOV,这里我们指定了i486p指令集。
你可能会疑惑为什么有+4+8。如果想理解这些数字出现的原因,就必须深入研究“函数的调用”。在函数调用时,实际上是把函数名推入到一个栈当中,此时ESP就指向了函数名,而ESP+4则指向了第一个参数addr,由于这是一个整型变量,占据4个字节的内存,因此下一个参数就在ESP+8当中。显而易见,我们从地址的层面获取了函数参数。
随后,我们修改C语言代码如下:

void io_hlt(void);
void write_mem8(int addr, int data); // 一定要进行函数声明!
void HariMain(void)
{
int * i;
for(i = 0xa0000; i <= 0xaffff; i++)
{
write_mem8(i, 15);
}
while (1)
{
io_hlt();
}
}

编译运行,可以发现此时系统的画面呈现一片雪白。

然而,我们知道C语言本身可以操纵内存,因此完全不需要大费周章再写一个write_mem8。如果你不想使用汇编,那么可以使用以下代码。

void io_hlt(void);
// 不需要void write_mem8(int addr, int data)也能执行
void HariMain(void)
{
char * i;
for(i = 0xa0000; i <= 0xaffff; i++)
{
*i = 15;
}
while (1)
{
io_hlt();
}
}

下面我们的任务是画出各式各样颜色的矩形方块,然而此时的颜色只有8种,完全不够用!为此,我们只能另求他法,使我们的程序足以输出RGB颜色。我们眼下需要的颜色如下:

C语言代码如下:

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 HariMain(void)
{
char * i;
init_palette();
for(i = 0xa0000; i <= 0xaffff; i++)
{
*i = (int)i & 0x0f;
}
while (1)
{
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00,
0xff, 0x00, 0x00,
0x00, 0xff, 0x00,
0xff, 0xff, 0x00,
0x00, 0x00, 0xff,
0x00, 0xff, 0xff,
0xff, 0x00, 0xff,
0xff, 0xff, 0xff,
0xc6, 0xc6, 0xc6,
0x84, 0x00, 0x00,
0x00, 0x84, 0x00,
0x84, 0x84, 0x00,
0x00, 0x00, 0x84,
0x84, 0x00, 0x84,
0x00, 0x84, 0x84,
0x84, 0x84, 0x84
};
set_palette(0, 15, table_rgb);
return;
}
void set_palette(int start, int end, unsigned char * rgb)
{
int i, eflags;
eflags = io_load_eflags();
io_cli();
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;
}

我们看到多了几个汇编函数,因此在汇编文件中补写上以下汇编函数:

[FORMAT "WCOFF"] ; 制作目标文件的格式
[INSTRSET "i486p"] ; 使用到486为止的指令
[BITS 32] ; 制作32位模式对应的机械语言
[FILE "naskfunc.nas"] ; 源文件名
GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt
GLOBAL _io_in8, _io_in16, _io_in32
GLOBAL _io_out8, _io_out16, _io_out32
GLOBAL _io_load_eflags, _io_store_eflags
[SECTION .text] ; 以下是函数本体
_io_hlt:
HLT
RET
_io_cli:
CLI
RET
_io_sti:
STI
RET
_io_stihlt:
STI
HLT
RET
_io_in8: ; int io_in8(int port)
MOV EDX, [ESP+4]
MOV EAX, 0
IN AL, DX
RET
_io_in16:
MOV EDX, [ESP+4]
MOV EAX, 0
IN AX, DX
RET
_io_in32:
MOV EDX, [ESP+4]
MOV EAX, 0
IN EAX, DX
RET
_io_out8: ; void io_out8(int port, int data)
MOV EDX, [ESP+4]
MOV AL, [ESP+8]
OUT DX, AL
RET
_io_out16:
MOV EDX, [ESP+4]
MOV AX, [ESP+8]
OUT DX, AX
RET
_io_out32:
MOV EDX, [ESP+4]
MOV EAX, [ESP+8]
OUT DX, EAX
RET
_io_load_eflags:
PUSHFD
POP EAX
RET
_io_store_eflags:
MOV EAX, [ESP+4]
PUSH EAX
POPFD
RET

前四个函数只是把汇编指令包装成了C语言可以调用的函数,后面关于io的汇编函数都在转移内存,例如_io_in8'就是读取[ESP+4]处的值之后返回到AL中,而_io_out8则是将数据data输入到指定端口port。注意,C语言在执行RET语句时,会默认EAX中的值为返回值。那么EFLAGS是什么呢?这个寄存器里储存着当前的进位信息,包含跳转的指令都会用到它(如JAE,JBE,JNC`等等)。但是我们在C语言代码中涉及到CLI,即清空中断标志(clear interrupt flag)和STI,即设置中断标志(set interrupt flag)。因此必须保留之前的进位信息,并在操作完毕之后恢复原有信息。

光说了汇编,忘说了C语言代码!先从init_palette函数说起,起手一个static char数组,如果仔细想想的话,是不是等价于汇编语言的DB指令!这么一来,我们实际上是在内存中专门开辟了一片空间来储存大量颜色的RGB值!
接下来就是set_palette函数,抛开保存和重置EFLAGS,我们看到程序先向0x03c8地址传入了第一个颜色的编号,随后持续向0x03c9地址传入颜色。这就是使用RGB颜色的方法:先在0x03c8里指定颜色编号(不是显存地址!),之后依次向0x03c9传入R,G,B三个通道的颜色。如果要继续指定颜色,则可以省略指定像素的一步,直接向0x03c9传入新颜色。

注意⚠️我们不是在直接绘制屏幕颜色!CPU会按照读入的顺序依次为颜色标号。例如,我们先传入的颜色是#000000,那么这个颜色就会记为0号颜色,而下一个颜色#FF0000则会被记为1号颜色。

类似地,如果想读出颜色,要先在0x03c7里指定目标像素在显存的位置,之后依次向0x03c9读出R,G,B三个通道的颜色。如果要继续读取颜色,则可以省略指定像素的一步,直接向0x03c9读取新颜色。

编译完毕后运行,可以发现此时输出变成了彩色条样。

这里是方块,那里也是

下面我们的任务升级:绘制特定颜色的矩形。这一步只需要对C语言代码稍作更改。

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 draw_rectangle(unsigned char * vram, int color, 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 * i;
init_palette();
draw_rectangle(0xa0000, 20, 20, 70, 50, COL8_FFFFFF);
while (1)
{
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00,
0xff, 0x00, 0x00,
0x00, 0xff, 0x00,
0xff, 0xff, 0x00,
0x00, 0x00, 0xff,
0x00, 0xff, 0xff,
0xff, 0x00, 0xff,
0xff, 0xff, 0xff,
0xc6, 0xc6, 0xc6,
0x84, 0x00, 0x00,
0x00, 0x84, 0x00,
0x84, 0x84, 0x00,
0x00, 0x00, 0x84,
0x84, 0x00, 0x84,
0x00, 0x84, 0x84,
0x84, 0x84, 0x84
};
set_palette(0, 15, table_rgb);
return;
}
void set_palette(int start, int end, unsigned char * rgb)
{
int i, eflags;
eflags = io_load_eflags();
io_cli();
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 draw_rectangle(unsigned char * vram, int color, int x0, int y0, int x1, int y1)
{
int i, j;
for(i = x0; i <= x1; i++)
for(j = y0; j <= y1; j++)
vram[i + 320 * j] = color;
return;
}

其中我们用到了一个公式:对于屏幕上的点坐标$(x,y)$,其内存地址为0xa0000 + x + 320 * y,其中320是横向分辨率。运行新的代码,可以发现此时屏幕上多出一个白色矩形。

下面,我们来绘制操作系统的整体界面:一个背景墙、一个任务栏、一个开始按钮、一个时间框。修改后的HariMain如下:

void HariMain(void)
{
char * i;
int xsize = 320;
int ysize = 200;
unsigned char * vram = 0xa0000;
init_palette();
draw_rectangle(vram, COL8_008484, 0, 0, xsize - 1, ysize - 29);
draw_rectangle(vram, COL8_C6C6C6, 0, ysize - 28, xsize - 1, ysize - 28);
draw_rectangle(vram, COL8_FFFFFF, 0, ysize - 27, xsize - 1, ysize - 27);
draw_rectangle(vram, COL8_C6C6C6, 0, ysize - 26, xsize - 1, ysize - 1);
draw_rectangle(vram, COL8_FFFFFF, 3, ysize - 24, 59, ysize - 24);
draw_rectangle(vram, COL8_FFFFFF, 2, ysize - 24, 2, ysize - 4);
draw_rectangle(vram, COL8_848484, 3, ysize - 4, 59, ysize - 4);
draw_rectangle(vram, COL8_848484, 59, ysize - 23, 59, ysize - 5);
draw_rectangle(vram, COL8_000000, 2, ysize - 3, 59, ysize - 3);
draw_rectangle(vram, COL8_000000, 60, ysize - 24, 60, ysize - 3);
draw_rectangle(vram, COL8_848484, xsize - 47, ysize - 24, xsize - 4, ysize - 24);
draw_rectangle(vram, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize - 4);
draw_rectangle(vram, COL8_FFFFFF, xsize - 47, ysize - 3, xsize - 4, ysize - 3);
draw_rectangle(vram, COL8_FFFFFF, xsize - 3, ysize - 24, xsize - 3, ysize - 3);
while (1)
{
io_hlt();
}
}

运行后是一个还算不错的操作系统界面。

初始信息的读取

在上一次的C语言代码中,我们人为声明了xsizeysizevram变量,实际上这些量都被我们保存起来过(就在asmhead.nas中)。

因此,我们可以直接从内存中读取对应的值。

void HariMain(void)
{
// 本次更改的部分
char * vram;
int xsize, ysize;
short *binfo_scrnx, *binfo_scrny;
int *binfo_vram;
init_palette();
binfo_scrnx = (short *) 0x0ff4;
binfo_scrny = (short *) 0x0ff6;
binfo_vram = (int *) 0x0ff8;
xsize = *binfo_scrnx;
ysize = *binfo_scrny;
vram = (char *) *binfo_vram;
...
}

更简洁明了的方式是使用结构体。

// 本次更改的部分
struct BOOTINFO
{
char cyls, leds, vmode, reserve;
short scrnx, scrny;
char *vram;
};
void HariMain(void)
{
char * vram;
int xsize, ysize;
struct BOOTINFO *binfo;
init_palette();
binfo = (struct BOOTINFO *) 0x0ff0;
xsize = binfo->scrnx;
ysize = binfo->scrny;
vram = binfo->vram;
...
}

重新编译运行,一切正常!

文字显示

先前我们打印字符都是调用的BIOS中断函数,但是在32位模式中我们不能使用BIOS了,只能自力更生地“画”出字符。

事实上,无论是哪种操作系统,字符都是靠像素点阵绘制的,而同一种字符的不同画法就对应于不同的“字体(font)”。我们采用$8\times 16$的空间来绘制字符。

我们来绘制一个字符“A”看看。首先录入“A”的数据。

static unsigned char font_A[16] = {
0x00, //0b00000000,
0x18, //0b00011000,
0x18, //0b00011000,
0x18, //0b00011000,
0x18, //0b00011000,
0x24, //0b00100100,
0x24, //0b00100100,
0x24, //0b00100100,
0x24, //0b00100100,
0x7e, //0b01111110,
0x42, //0b01000010,
0x42, //0b01000010,
0xe7, //0b11100111,
0x00, //0b00000000,
0x00, //0b00000000,
};

随后再加入一个在指定位置输出字符的函数(不要忘记在代码最前部分添加函数声明!):

void putfont8(char *vram, int xsize, int x, int y, char c, char * font)
{
int i;
char d;
for(i = 0; i < 16; i++) {
d = font[i];
if((d & 0x80) != 0) vram[(y + i) * xsize + x + 0] = c; // 0x80 = 0b10000000
if((d & 0x40) != 0) vram[(y + i) * xsize + x + 1] = c; // 0x40 = 0b01000000
if((d & 0x20) != 0) vram[(y + i) * xsize + x + 2] = c; // 0x20 = 0b00100000
if((d & 0x10) != 0) vram[(y + i) * xsize + x + 3] = c; // 0x10 = 0b00010000
if((d & 0x08) != 0) vram[(y + i) * xsize + x + 4] = c; // 0x08 = 0b00001000
if((d & 0x04) != 0) vram[(y + i) * xsize + x + 5] = c; // 0x04 = 0b00000100
if((d & 0x02) != 0) vram[(y + i) * xsize + x + 6] = c; // 0x02 = 0b00000010
if((d & 0x01) != 0) vram[(y + i) * xsize + x + 7] = c; // 0x01 = 0b00000001
}
}

HariMain主函数中绘制桌面后,添加如下语句:

static unsigned char font_A[16] = {
0x00, //0b00000000,
0x18, //0b00011000,
0x18, //0b00011000,
0x18, //0b00011000,
0x18, //0b00011000,
0x24, //0b00100100,
0x24, //0b00100100,
0x24, //0b00100100,
0x24, //0b00100100,
0x7e, //0b01111110,
0x42, //0b01000010,
0x42, //0b01000010,
0xe7, //0b11100111,
0x00, //0b00000000,
0x00, //0b00000000,
};
putfont8(vram, xsize, 20, 20, COL8_FFFFFF, font_A);

编译运行,大功告成!

putfont8中我们看到了&运算符,其实这个函数的原理就是每8位处理一次,如果8位中任意一个地方出现了1,那么就在对应格点输出指定颜色。

我们现在只手工输入了一个字符,要知道ASCII码对应了多少字符,我们原则上就应该准备多少字符。这里我们新建一个txt文件来储存我们的字体信息,取名为font.txt,并把下面内容复制到文件中。

char 0x00
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x01
........
........
..***...
.*...*..
*.....*.
*.*.*.*.
*.*.*.*.
*.....*.
*.....*.
*.*.*.*.
*..*..*.
.*...*..
..***...
........
........
........
char 0x02
........
........
..***...
.*****..
*******.
**.*.**.
**.*.**.
*******.
*******.
**.*.**.
***.***.
.*****..
..***...
........
........
........
char 0x03
........
........
........
........
.**.**..
*******.
*******.
*******.
.*****..
..***...
...*....
........
........
........
........
........
char 0x04
........
........
........
........
...*....
..***...
.*****..
*******.
.*****..
..***...
...*....
........
........
........
........
........
char 0x05
........
........
........
........
...*....
..***...
.*.*.*..
*******.
.*.*.*..
...*....
..***...
........
........
........
........
........
char 0x06
........
........
........
........
...*....
..***...
.*****..
*******.
**.*.**.
...*....
..***...
........
........
........
........
........
char 0x07
........
........
........
........
........
........
...**...
..****..
..****..
...**...
........
........
........
........
........
........
char 0x08
********
********
********
********
********
********
***..***
**....**
**....**
***..***
********
********
********
********
********
********
char 0x09
........
........
........
........
........
..****..
.**..**.
.*....*.
.*....*.
.**..**.
..****..
........
........
........
........
........
char 0x0a
********
********
********
********
********
**....**
*..**..*
*.****.*
*.****.*
*..**..*
**....**
********
********
********
********
********
char 0x0b
........
...*....
..***...
.*.*.*..
*..*..*.
...*....
...*....
..***...
.*...*..
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x0c
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
.*...*..
..***...
...*....
...*....
*******.
...*....
...*....
...*....
........
........
char 0x0d
........
........
....**..
....***.
....*.**
....*.**
....*.*.
....*...
....*...
...**...
.****...
*****...
.***....
........
........
........
char 0x0e
........
........
...*****
...*****
...*...*
...*...*
...*...*
...*...*
...*...*
...*...*
.***.***
********
.**..**.
........
........
........
char 0x0f
........
........
........
........
...*....
.*.*.*..
..***...
..*.*...
..***...
.*.*.*..
...*....
........
........
........
........
........
char 0x10
........
*.......
**......
***.....
****....
*****...
******..
*******.
******..
*****...
****....
***.....
**......
*.......
........
........
char 0x11
........
......*.
.....**.
....***.
...****.
..*****.
.******.
*******.
.******.
..*****.
...****.
....***.
.....**.
......*.
........
........
char 0x12
........
........
...*....
..***...
.*.*.*..
*..*..*.
...*....
...*....
...*....
*..*..*.
.*.*.*..
..***...
...*....
........
........
........
char 0x13
........
........
.*...*..
.*...*..
.*...*..
.*...*..
.*...*..
.*...*..
.*...*..
.*...*..
........
........
.*...*..
.*...*..
........
........
char 0x14
........
..*****.
.*..*.*.
*...*.*.
*...*.*.
*...*.*.
*...*.*.
.*..*.*.
..***.*.
....*.*.
....*.*.
....*.*.
....*.*.
....*.*.
........
........
char 0x15
.*****..
*.....*.
.*......
..*.....
..***...
.*...*..
*.....*.
*.....*.
*.....*.
.*...*..
..***...
....*...
.....*..
*.....*.
.*****..
........
char 0x16
........
........
........
........
........
........
........
........
........
........
........
*******.
*******.
*******.
........
........
char 0x17
........
........
...*....
..***...
.*.*.*..
*..*..*.
...*....
...*....
...*....
*..*..*.
.*.*.*..
..***...
...*....
.*****..
........
........
char 0x18
........
...*....
..***...
.*.*.*..
*..*..*.
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0x19
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
*..*..*.
.*.*.*..
..***...
...*....
........
........
char 0x1a
........
........
........
........
...*....
....*...
.....*..
*******.
.....*..
....*...
...*....
........
........
........
........
........
char 0x1b
........
........
........
........
...*....
..*.....
.*......
*******.
.*......
..*.....
...*....
........
........
........
........
........
char 0x1c
........
........
........
........
........
........
........
........
........
........
........
*.......
*.......
*******.
........
........
char 0x1d
........
........
........
........
........
..*.*...
.*...*..
*******.
.*...*..
..*.*...
........
........
........
........
........
........
char 0x1e
........
........
........
........
...*....
...*....
..***...
..***...
.*****..
.*****..
*******.
*******.
........
........
........
........
char 0x1f
........
........
........
........
*******.
*******.
.*****..
.*****..
..***...
..***...
...*....
...*....
........
........
........
........
char 0x20
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x21
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
...*....
...*....
........
........
char 0x22
..*.*...
..*.*...
..*.*...
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x23
........
.*...*..
.*...*..
.*...*..
*******.
.*...*..
.*...*..
.*...*..
.*...*..
.*...*..
*******.
.*...*..
.*...*..
.*...*..
........
........
char 0x24
...*....
..***.*.
.*.*.**.
*..*..*.
*..*..*.
*..*....
.*.*....
..***...
...*.*..
...*..*.
*..*..*.
*..*..*.
**.*.*..
*.***...
...*....
...*....
char 0x25
.**...*.
*..*..*.
*..*.*..
*..*.*..
.**.*...
....*...
...*....
...*....
..*.....
..*.**..
.*.*..*.
.*.*..*.
*..*..*.
*...**..
........
........
char 0x26
........
.***....
*...*...
*...*...
*...*...
*..*....
.**.....
.*...***
*.*...*.
*..*..*.
*...*.*.
*....*..
.*...**.
..***..*
........
........
char 0x27
.....*..
....*...
...*....
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x28
......*.
.....*..
....*...
....*...
...*....
...*....
...*....
...*....
...*....
...*....
...*....
....*...
....*...
.....*..
......*.
........
char 0x29
*.......
.*......
..*.....
..*.....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
..*.....
..*.....
.*......
*.......
........
char 0x2a
........
........
........
........
........
...*....
*..*..*.
.*.*.*..
..***...
.*.*.*..
*..*..*.
...*....
........
........
........
........
char 0x2b
........
........
........
........
........
...*....
...*....
...*....
*******.
...*....
...*....
...*....
........
........
........
........
char 0x2c
........
........
........
........
........
........
........
........
........
........
........
...**...
...**...
....*...
....*...
...*....
char 0x2d
........
........
........
........
........
........
........
........
*******.
........
........
........
........
........
........
........
char 0x2e
........
........
........
........
........
........
........
........
........
........
........
........
...**...
...**...
........
........
char 0x2f
......*.
......*.
.....*..
.....*..
....*...
....*...
....*...
...*....
...*....
..*.....
..*.....
.*......
.*......
.*......
*.......
*.......
char 0x30
........
...**...
..*..*..
..*..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
..*..*..
..*..*..
...**...
........
........
char 0x31
........
....*...
...**...
..*.*...
....*...
....*...
....*...
....*...
....*...
....*...
....*...
....*...
....*...
..*****.
........
........
char 0x32
........
...**...
..*..*..
.*....*.
.*....*.
......*.
.....*..
....*...
...*....
..*.....
..*.....
.*......
.*......
.******.
........
........
char 0x33
........
...**...
..*..*..
.*....*.
......*.
......*.
.....*..
...**...
.....*..
......*.
......*.
.*....*.
..*..*..
...**...
........
........
char 0x34
........
....**..
....**..
....**..
...*.*..
...*.*..
...*.*..
..*..*..
..*..*..
.*...*..
.******.
.....*..
.....*..
...****.
........
........
char 0x35
........
.*****..
.*......
.*......
.*......
.*.**...
.**..*..
......*.
......*.
......*.
......*.
.*....*.
..*..*..
...**...
........
........
char 0x36
........
...**...
..*..*..
.*....*.
.*......
.*.**...
.**..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
..*..*..
...**...
........
........
char 0x37
........
.******.
.*....*.
.*....*.
.....*..
.....*..
....*...
....*...
....*...
...*....
...*....
...*....
...*....
..***...
........
........
char 0x38
........
...**...
..*..*..
.*....*.
.*....*.
.*....*.
..*..*..
...**...
..*..*..
.*....*.
.*....*.
.*....*.
..*..*..
...**...
........
........
char 0x39
........
...**...
..*..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
..*..**.
...**.*.
......*.
.*....*.
..*..*..
...**...
........
........
char 0x3a
........
........
........
........
........
...**...
...**...
........
........
........
........
........
...**...
...**...
........
........
char 0x3b
........
........
........
........
........
...**...
...**...
........
........
........
........
...**...
...**...
....*...
....*...
...*....
char 0x3c
........
......*.
.....*..
....*...
...*....
..*.....
.*......
*.......
*.......
.*......
..*.....
...*....
....*...
.....*..
......*.
........
char 0x3d
........
........
........
........
........
........
*******.
........
........
*******.
........
........
........
........
........
........
char 0x3e
........
*.......
.*......
..*.....
...*....
....*...
.....*..
......*.
......*.
.....*..
....*...
...*....
..*.....
.*......
*.......
........
char 0x3f
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
.....*..
....*...
...*....
...*....
........
........
...**...
...**...
........
........
char 0x40
........
..***...
.*...*..
*.....*.
*..**.*.
*.*.*.*.
*.*.*.*.
*.*.*.*.
*.*.*.*.
*.*.*.*.
*..***..
*.......
.*...**.
..***...
........
........
char 0x41
........
...**...
...**...
...**...
...**...
..*..*..
..*..*..
..*..*..
..*..*..
.******.
.*....*.
.*....*.
.*....*.
***..***
........
........
char 0x42
........
****....
.*..*...
.*...*..
.*...*..
.*...*..
.*..*...
.****...
.*...*..
.*....*.
.*....*.
.*....*.
.*...*..
*****...
........
........
char 0x43
........
..***.*.
.*...**.
.*....*.
*.....*.
*.......
*.......
*.......
*.......
*.......
*.....*.
.*....*.
.*...*..
..***...
........
........
char 0x44
........
*****...
.*...*..
.*...*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*...*..
.*...*..
*****...
........
........
char 0x45
........
*******.
.*....*.
.*....*.
.*......
.*......
.*...*..
.*****..
.*...*..
.*......
.*......
.*....*.
.*....*.
*******.
........
........
char 0x46
........
*******.
.*....*.
.*....*.
.*......
.*......
.*...*..
.*****..
.*...*..
.*...*..
.*......
.*......
.*......
****....
........
........
char 0x47
........
..***.*.
.*...**.
.*....*.
*.....*.
*.......
*.......
*..****.
*.....*.
*.....*.
*.....*.
.*....*.
.*...**.
..***...
........
........
char 0x48
........
***..***
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.******.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
***..***
........
........
char 0x49
........
.*****..
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
.*****..
........
........
char 0x4a
........
...*****
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
*....*..
.*..*...
..**....
........
char 0x4b
........
***..***
.*....*.
.*...*..
.*..*...
.*.*....
.*.*....
.**.....
.*.*....
.*.*....
.*..*...
.*...*..
.*....*.
***..***
........
........
char 0x4c
........
****....
.*......
.*......
.*......
.*......
.*......
.*......
.*......
.*......
.*......
.*....*.
.*....*.
*******.
........
........
char 0x4d
........
**....**
.*....*.
.**..**.
.**..**.
.**..**.
.*.**.*.
.*.**.*.
.*.**.*.
.*....*.
.*....*.
.*....*.
.*....*.
***..***
........
........
char 0x4e
........
**...***
.*....*.
.**...*.
.**...*.
.*.*..*.
.*.*..*.
.*.*..*.
.*..*.*.
.*..*.*.
.*..*.*.
.*...**.
.*...**.
***...*.
........
........
char 0x4f
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x50
........
*****...
.*...*..
.*....*.
.*....*.
.*....*.
.*...*..
.****...
.*......
.*......
.*......
.*......
.*......
****....
........
........
char 0x51
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*..*..*.
*...*.*.
.*...*..
..***.*.
........
........
char 0x52
........
******..
.*....*.
.*....*.
.*....*.
.*....*.
.*****..
.*...*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
***..***
........
........
char 0x53
........
..***.*.
.*...**.
*.....*.
*.....*.
*.......
.*......
..***...
.....*..
......*.
*.....*.
*.....*.
**...*..
*.***...
........
........
char 0x54
........
*******.
*..*..*.
*..*..*.
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
.*****..
........
........
char 0x55
........
***..***
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
..*..*..
..****..
........
........
char 0x56
........
***..***
.*....*.
.*....*.
.*....*.
.*....*.
..*..*..
..*..*..
..*..*..
..*..*..
...**...
...**...
...**...
...**...
........
........
char 0x57
........
***..***
.*....*.
.*....*.
.*....*.
.*.**.*.
.*.**.*.
.*.**.*.
.*.**.*.
..*..*..
..*..*..
..*..*..
..*..*..
..*..*..
........
........
char 0x58
........
***..***
.*....*.
.*....*.
..*..*..
..*..*..
..*..*..
...**...
..*..*..
..*..*..
..*..*..
.*....*.
.*....*.
***..***
........
........
char 0x59
........
***.***.
.*...*..
.*...*..
.*...*..
..*.*...
..*.*...
..*.*...
...*....
...*....
...*....
...*....
...*....
.*****..
........
........
char 0x5a
........
*******.
*....*..
*....*..
....*...
....*...
...*....
...*....
..*.....
..*.....
.*......
.*....*.
*.....*.
*******.
........
........
char 0x5b
........
..*****.
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*.....
..*****.
........
char 0x5c
*.......
*.......
.*......
.*......
..*.....
..*.....
..*.....
...*....
...*....
....*...
....*...
.....*..
.....*..
.....*..
......*.
......*.
char 0x5d
........
.*****..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.*****..
........
char 0x5e
........
...*....
..*.*...
.*...*..
*.....*.
........
........
........
........
........
........
........
........
........
........
........
char 0x5f
........
........
........
........
........
........
........
........
........
........
........
........
........
........
*******.
........
char 0x60
...*....
....*...
.....*..
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x61
........
........
........
........
........
.***....
....*...
.....*..
..****..
.*...*..
*....*..
*....*..
*...**..
.***.**.
........
........
char 0x62
**......
.*......
.*......
.*......
.*......
.*.**...
.**..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.**..*..
.*.**...
........
........
char 0x63
........
........
........
........
........
..**....
.*..**..
*....*..
*....*..
*.......
*.......
*.....*.
.*...*..
..***...
........
........
char 0x64
....**..
.....*..
.....*..
.....*..
.....*..
..**.*..
.*..**..
*....*..
*....*..
*....*..
*....*..
*....*..
.*..**..
..**.**.
........
........
char 0x65
........
........
........
........
........
..***...
.*...*..
*.....*.
*.....*.
******..
*.......
*.....*.
.*....*.
..****..
........
........
char 0x66
....***.
...*....
...*....
...*....
...*....
.*****..
...*....
...*....
...*....
...*....
...*....
...*....
...*....
.*****..
........
........
char 0x67
........
........
........
........
........
..**.**.
.*..**..
*....*..
*....*..
*....*..
*....*..
.*..**..
..**.*..
.....*..
.....*..
.****...
char 0x68
**......
.*......
.*......
.*......
.*......
.*.**...
.**..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
***...**
........
........
char 0x69
........
...*....
...*....
........
........
..**....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
..***...
........
........
char 0x6a
........
.....*..
.....*..
........
........
....**..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
.....*..
....*...
....*...
..**....
char 0x6b
**......
.*......
.*......
.*......
.*......
.*..***.
.*...*..
.*..*...
.*.*....
.**.....
.*.*....
.*..*...
.*...*..
***..**.
........
........
char 0x6c
..**....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
..***...
........
........
char 0x6d
........
........
........
........
........
****.**.
.*..*..*
.*..*..*
.*..*..*
.*..*..*
.*..*..*
.*..*..*
.*..*..*
**.**.**
........
........
char 0x6e
........
........
........
........
........
**.**...
.**..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
***...**
........
........
char 0x6f
........
........
........
........
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x70
........
........
........
........
........
**.**...
.**..*..
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.**..*..
.*.**...
.*......
***.....
char 0x71
........
........
........
........
........
..**.*..
.*..**..
*....*..
*....*..
*....*..
*....*..
*....*..
.*..**..
..**.*..
.....*..
....***.
char 0x72
........
........
........
........
........
**.***..
.**...*.
.*....*.
.*......
.*......
.*......
.*......
.*......
***.....
........
........
char 0x73
........
........
........
........
........
.****.*.
*....**.
*.....*.
**......
..***...
.....**.
*.....*.
**....*.
*.****..
........
........
char 0x74
........
........
...*....
...*....
...*....
.*****..
...*....
...*....
...*....
...*....
...*....
...*....
...*....
....***.
........
........
char 0x75
........
........
........
........
........
**...**.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*....*.
.*...**.
..***.**
........
........
char 0x76
........
........
........
........
........
***..***
.*....*.
.*....*.
.*....*.
..*..*..
..*..*..
..*..*..
...**...
...**...
........
........
char 0x77
........
........
........
........
........
***..***
.*....*.
.*....*.
.*.**.*.
.*.**.*.
.*.**.*.
..*..*..
..*..*..
..*..*..
........
........
char 0x78
........
........
........
........
........
**...**.
.*...*..
..*.*...
..*.*...
...*....
..*.*...
..*.*...
.*...*..
**...**.
........
........
char 0x79
........
........
........
........
........
***..***
.*....*.
.*....*.
..*..*..
..*..*..
..*..*..
...**...
...**...
...*....
...*....
.**.....
char 0x7a
........
........
........
........
........
*******.
*.....*.
*....*..
....*...
...*....
..*.....
.*....*.
*.....*.
*******.
........
........
char 0x7b
........
.....**.
....*...
...*....
...*....
...*....
...*....
.**.....
...*....
...*....
...*....
...*....
....*...
.....**.
........
........
char 0x7c
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0x7d
........
.**.....
...*....
....*...
....*...
....*...
....*...
.....**.
....*...
....*...
....*...
....*...
...*....
.**.....
........
........
char 0x7e
........
.***..*.
*...**..
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0x7f
........
........
........
........
...*....
..*.*...
.*...*..
*.....*.
*******.
*.....*.
*******.
........
........
........
........
........
char 0x80
........
..***...
.*...*..
*.....*.
*.......
*.......
*.......
*.......
*.......
*.......
*.......
*.....*.
.*...*..
..***...
...*....
..*.....
char 0x81
........
........
..*..*..
..*..*..
........
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*....*.
..*****.
........
........
char 0x82
....**..
....*...
...*....
........
........
..***...
.*...*..
*.....*.
*.....*.
*******.
*.......
*.....*.
.*...*..
..***...
........
........
char 0x83
........
...*....
..*.*...
.*...*..
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
........
char 0x84
........
........
..*..*..
..*..*..
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
........
char 0x85
...*....
....*...
.....*..
........
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
........
char 0x86
........
...**...
..*..*..
...**...
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
........
char 0x87
........
........
........
........
........
..****..
.*....*.
*.......
*.......
*.......
*.......
*.......
.*....*.
..****..
....*...
...*....
char 0x88
........
...*....
..*.*...
.*...*..
........
..***...
.*...*..
*.....*.
*.....*.
*******.
*.......
*.....*.
.*...*..
..***...
........
........
char 0x89
........
........
..*..*..
..*..*..
........
..***...
.*...*..
*.....*.
*.....*.
*******.
*.......
*.....*.
.*...*..
..***...
........
........
char 0x8a
...*....
....*...
.....*..
........
........
..***...
.*...*..
*.....*.
*.....*.
*******.
*.......
*.....*.
.*...*..
..***...
........
........
char 0x8b
........
........
..*..*..
..*..*..
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0x8c
........
...*....
..*.*...
.*...*..
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0x8d
...*....
....*...
.....*..
........
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0x8e
..*..*..
..*..*..
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*******.
*.....*.
*.....*.
*.....*.
*.....*.
........
........
char 0x8f
........
..***...
.*...*..
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*******.
*.....*.
*.....*.
*.....*.
*.....*.
........
........
char 0x90
....**..
....*...
...*....
*******.
*.......
*.......
*.......
*.......
*****...
*.......
*.......
*.......
*.......
*******.
........
........
char 0x91
........
........
........
........
........
.**.....
...***..
...*..*.
.***..*.
*..****.
*..*....
*..*....
*..*..*.
.**.**..
........
........
char 0x92
....**..
...*....
..*.....
..*.*...
..*.*...
..*.*...
*******.
..*.*...
..*.*...
..*.*...
..*.*...
..*.*...
..*.*...
..*.*...
........
........
char 0x93
........
...*....
..*.*...
.*...*..
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x94
........
........
..*..*..
..*..*..
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x95
...*....
....*...
.....*..
........
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x96
........
...*....
..*.*...
.*...*..
........
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*....*.
..*****.
........
........
char 0x97
...*....
....*...
.....*..
........
........
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*....*.
..*****.
........
........
char 0x98
........
........
..*..*..
..*..*..
........
*.....*.
*.....*.
.*...*..
.*...*..
..*.*...
..*.*...
...*....
...*....
..*.....
..*.....
.*......
char 0x99
..*..*..
..*..*..
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x9a
..*..*..
..*..*..
........
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0x9b
........
..*.*...
..*.*...
..*.*...
..****..
.**.*.*.
*.*.*...
*.*.*...
*.*.*...
*.*.*...
*.*.*...
.**.*.*.
..****..
..*.*...
..*.*...
..*.*...
char 0x9c
........
....**..
...*..*.
..*.....
..*.....
..*.....
******..
..*.....
..*.....
..*.....
.**.....
*.*.....
*.**..*.
.*..**..
........
........
char 0x9d
........
*.....*.
*.....*.
.*...*..
..*.*...
...*....
*******.
...*....
...*....
*******.
...*....
...*....
...*....
...*....
........
........
char 0x9e
........
***.....
*..*....
*...*...
*...*...
*...*...
*..*.*..
***..*..
*..*****
*....*..
*....*..
*....*..
*....*..
*....*..
........
........
char 0x9f
........
....**..
...*..*.
...*....
...*....
...*....
*******.
...*....
...*....
...*....
...*....
...*....
*..*....
.**.....
........
........
char 0xa0
....**..
....*...
...*....
........
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
........
char 0xa1
....**..
....*...
...*....
........
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0xa2
....**..
....*...
...*....
........
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0xa3
....**..
....*...
...*....
........
........
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*....*.
..*****.
........
........
char 0xa4
........
...*..*.
..*.*.*.
..*..*..
........
*****...
*....*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
........
........
char 0xa5
...*..*.
..*.*.*.
..*..*..
........
*.....*.
**....*.
**....*.
*.*...*.
*..*..*.
*..*..*.
*...*.*.
*....**.
*....**.
*.....*.
........
........
char 0xa6
........
........
........
.****...
.....*..
.....*..
..****..
.*...*..
*....*..
*....*..
.*...*..
..*****.
........
*******.
........
........
char 0xa7
........
........
........
..***...
.*...*..
*.....*.
*.....*.
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
*******.
........
........
char 0xa8
........
...*....
...*....
........
........
...*....
...*....
..*.....
.*...*..
*.....*.
*.....*.
*.....*.
.*...*..
..***...
........
........
char 0xa9
........
........
........
........
........
........
........
........
........
........
*******.
*.......
*.......
*.......
........
........
char 0xaa
........
........
........
........
........
........
........
........
........
........
*******.
......*.
......*.
......*.
........
........
char 0xab
........
...*....
..**....
...*....
...*....
...*....
........
*******.
........
.****...
.....*..
..***...
.*......
.*****..
........
........
char 0xac
........
...*....
..**....
...*....
...*....
...*....
........
*******.
........
...**...
..*.*...
.*..*...
.*****..
....*...
........
........
char 0xad
........
...*....
...*....
........
........
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
........
........
char 0xae
........
........
........
........
...*..*.
..*..*..
.*..*...
*..*....
*..*....
.*..*...
..*..*..
...*..*.
........
........
........
........
char 0xaf
........
........
........
........
*..*....
.*..*...
..*..*..
...*..*.
...*..*.
..*..*..
.*..*...
*..*....
........
........
........
........
char 0xb0
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
...*...*
.*...*..
char 0xb1
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
.*.*.*.*
*.*.*.*.
char 0xb2
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
.***.***
**.***.*
char 0xb3
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xb4
...*....
...*....
...*....
...*....
...*....
...*....
...*....
****....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xb5
...*....
...*....
...*....
...*....
...*....
...*....
...*....
****....
...*....
****....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xb6
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xb7
........
........
........
........
........
........
........
******..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xb8
........
........
........
........
........
........
........
****....
...*....
****....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xb9
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.*..
.....*..
****.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xba
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xbb
........
........
........
........
........
........
........
******..
.....*..
****.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xbc
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.*..
.....*..
******..
........
........
........
........
........
........
char 0xbd
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
******..
........
........
........
........
........
........
........
........
char 0xbe
...*....
...*....
...*....
...*....
...*....
...*....
...*....
****....
...*....
****....
........
........
........
........
........
........
char 0xbf
........
........
........
........
........
........
........
****....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xc0
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*****
........
........
........
........
........
........
........
........
char 0xc1
...*....
...*....
...*....
...*....
...*....
...*....
...*....
********
........
........
........
........
........
........
........
........
char 0xc2
........
........
........
........
........
........
........
********
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xc3
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*****
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xc4
........
........
........
........
........
........
........
********
........
........
........
........
........
........
........
........
char 0xc5
...*....
...*....
...*....
...*....
...*....
...*....
...*....
********
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xc6
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*****
...*....
...*****
...*....
...*....
...*....
...*....
...*....
...*....
char 0xc7
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xc8
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.***
...*....
...*****
........
........
........
........
........
........
char 0xc9
........
........
........
........
........
........
........
...*****
...*....
...*.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xca
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.***
........
********
........
........
........
........
........
........
char 0xcb
........
........
........
........
........
........
........
********
........
****.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xcc
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.***
...*....
...*.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xcd
........
........
........
........
........
........
........
********
........
********
........
........
........
........
........
........
char 0xce
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.***
........
****.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xcf
...*....
...*....
...*....
...*....
...*....
...*....
...*....
********
........
********
........
........
........
........
........
........
char 0xd0
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
********
........
........
........
........
........
........
........
........
char 0xd1
........
........
........
........
........
........
........
********
........
********
...*....
...*....
...*....
...*....
...*....
...*....
char 0xd2
........
........
........
........
........
........
........
********
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xd3
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*****
........
........
........
........
........
........
........
........
char 0xd4
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*****
...*....
...*****
........
........
........
........
........
........
char 0xd5
........
........
........
........
........
........
........
...*****
...*....
...*****
...*....
...*....
...*....
...*....
...*....
...*....
char 0xd6
........
........
........
........
........
........
........
...*****
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xd7
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
****.***
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
...*.*..
char 0xd8
...*....
...*....
...*....
...*....
...*....
...*....
...*....
********
...*....
********
...*....
...*....
...*....
...*....
...*....
...*....
char 0xd9
...*....
...*....
...*....
...*....
...*....
...*....
...*....
****....
........
........
........
........
........
........
........
........
char 0xda
........
........
........
........
........
........
........
...*****
...*....
...*....
...*....
...*....
...*....
...*....
...*....
...*....
char 0xdb
********
********
********
********
********
********
********
********
********
********
********
********
********
********
********
********
char 0xdc
........
........
........
........
........
........
........
........
********
********
********
********
********
********
********
********
char 0xdd
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
****....
char 0xde
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
....****
char 0xdf
********
********
********
********
********
********
********
********
........
........
........
........
........
........
........
........
char 0xe0
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe1
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe2
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe3
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe4
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe5
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe6
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe7
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe8
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xe9
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xea
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xeb
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xec
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xed
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xee
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xef
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf0
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf1
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf2
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf3
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf4
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf5
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf6
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf7
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf8
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xf9
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xfa
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xfb
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xfc
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xfd
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xfe
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
char 0xff
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........
........

如果想正常使用这个“字体库”,必须使用z_tools里的makefont.exe进行编译,最后和bootpack.obj合并。因此,我们更新Makefile文件如下:

TOOLPATH = ../z_tools/
INCPATH = ../z_tools/haribote/
MAKE = $(TOOLPATH)make.exe -r
NASK = $(TOOLPATH)nask.exe
FONT = $(TOOLPATH)makefont.exe # 制作字体(txt->bin)
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM = $(TOOLPATH)obj2bim.exe
BIM2HRB = $(TOOLPATH)bim2hrb.exe
BIN2OBJ = $(TOOLPATH)bin2obj.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG = $(TOOLPATH)edimg.exe
IMGTOL = $(TOOLPATH)imgtol.com
COPY = copy
DEL = del
# 默认动作
default :
$(MAKE) img
# 镜像文件生成
ipl.bin : ipl.nas Makefile
$(NASK) ipl.nas ipl.bin ipl.lst
asmhead.bin : asmhead.nas Makefile
$(NASK) asmhead.nas asmhead.bin asmhead.lst
# 先编译成bin文件
font.bin : font.txt Makefile
$(FONT) font.txt font.bin
bootpack.gas : bootpack.c Makefile
$(CC1) -o bootpack.gas bootpack.c
bootpack.nas : bootpack.gas Makefile
$(GAS2NASK) bootpack.gas bootpack.nas
bootpack.obj : bootpack.nas Makefile
$(NASK) bootpack.nas bootpack.obj bootpack.lst
naskfunc.obj : naskfunc.nas Makefile
$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst
# 再编译成obj文件
font.obj: font.bin Makefile
$(BIN2OBJ) font.bin font.obj _font
bootpack.bim : bootpack.obj naskfunc.obj font.obj Makefile
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
bootpack.obj naskfunc.obj font.obj
# 3MB+64KB=3136KB
bootpack.hrb : bootpack.bim Makefile
$(BIM2HRB) bootpack.bim bootpack.hrb 0
os.sys : asmhead.bin bootpack.hrb Makefile
copy /B asmhead.bin+bootpack.hrb os.sys
os.img : ipl.bin os.sys Makefile
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
wbinimg src:ipl.bin len:512 from:0 to:0 \
copy from:os.sys to:@: \
imgout:os.img
# 其他指令
img :
$(MAKE) os.img
run :
$(MAKE) img
$(COPY) os.img ..\z_tools\qemu\fdimage0.bin
$(MAKE) -C ../z_tools/qemu
install :
$(MAKE) img
$(IMGTOL) w a: os.img
clean :
-$(DEL) *.bin
-$(DEL) *.lst
-$(DEL) *.gas
-$(DEL) *.obj
-$(DEL) bootpack.nas
-$(DEL) bootpack.map
-$(DEL) bootpack.bim
-$(DEL) bootpack.hrb
-$(DEL) *.sys
src_only :
$(MAKE) clean
-$(DEL) os.img

这下我们就不用手写字符'A'的像素点了,直接拿来用!但是在使用之前必须在bootpack.c里加上一句话:

extern char font[4096];

之后我们就可以自由调用字体库啦!

putfont8(vram, xsize, 20, 20, COL8_FFFFFF, font + 'A' * 16);
putfont8(vram, xsize, 28, 20, COL8_FFFFFF, font + 'B' * 16);
putfont8(vram, xsize, 36, 20, COL8_FFFFFF, font + 'C' * 16);

完整代码如下:

点击查看完整代码

编译运行后成功输出了ABC三个字符!

那么我们刚刚是如何做到的呢?其实这个字体库完全是为了阅读直观简单而制造出来的,实际上我们只是用汇编语言做了这样的事情:

_font:
DB ... ; 此处省略256个字符的8×16个数据,最终等于4096个字节。

也就是说我们把这些字符编码存放到了内存的固定位置!那么我们该如何访问呢?很简单,和_io_in8等函数一样,汇编语言以下划线_开头的名称到C语言中全部去掉下划线!但是我们得知道这块内存到底存放了什么类型的数据,因此我们要写char font[4096]。而extern则表示我们要从外部找这个数组,而不是重新创建,否则我们就访问了一片新内存,里面全是0!那么为什么在使用时要用font + 'A' * 16呢?这其实是一步指针运算,每个char类型的变量就是一个字节(8个比特),而我们的字体库是按照ASCII码排列的,因此'A'字符的数据就储存在font + 'A' * 16开始的16个字节里!

显示字符串和数字

下面我们的任务是显示一个完整的字符串。有了字体库和putfont8函数,我们可以轻易地实现输出字符串功能(不要忘了在代码最前面加上函数声明!)。

void putfont8_str(char *vram, int xsize, int x, int y, char c, unsigned char * str)
{
for(;*str != 0x00; str++) {
putfont8(vram, xsize, x, y, c, font + *str * 16);
x += 8;
if(x >= xsize) { // 支持换行
x %= 320;
y += 16;
}
}
}

为了支持数字的输出,我们必须使用stdio.h里的sprinf函数。如果我们想显示此时的分辨率,就可以写出如下代码:

char s[40];
sprintf(s, "screen x: %d, screen y: %d", binfo->scrnx, binfo->scrny);
putfont8_str(vram, xsize, 8, 8, COL8_FFFFFF, s);
点击查看完整代码
#include "stdio.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(int start, int end, unsigned char *rgb);
void draw_rectangle(unsigned char * vram, int xsize, int color, int x0, int y0, int x1, int y1);
void putfont8(char *vram, int xsize, int x, int y, char c, char * font);
void putfont8_str(char *vram, int xsize, int x, int y, char c, unsigned char * str);
#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
extern char font[4096];
struct BOOTINFO
{
char cyls, leds, vmode, reserve;
short scrnx, scrny;
char *vram;
};
void HariMain(void)
{
char * vram;
int xsize, ysize;
struct BOOTINFO *binfo;
init_palette();
binfo = (struct BOOTINFO *) 0x0ff0;
xsize = binfo->scrnx;
ysize = binfo->scrny;
vram = binfo->vram;
draw_rectangle(vram, xsize, COL8_008484, 0, 0, xsize - 1, ysize - 29);
draw_rectangle(vram, xsize, COL8_C6C6C6, 0, ysize - 28, xsize - 1, ysize - 28);
draw_rectangle(vram, xsize, COL8_FFFFFF, 0, ysize - 27, xsize - 1, ysize - 27);
draw_rectangle(vram, xsize, COL8_C6C6C6, 0, ysize - 26, xsize - 1, ysize - 1);
draw_rectangle(vram, xsize, COL8_FFFFFF, 3, ysize - 24, 59, ysize - 24);
draw_rectangle(vram, xsize, COL8_FFFFFF, 2, ysize - 24, 2, ysize - 4);
draw_rectangle(vram, xsize, COL8_848484, 3, ysize - 4, 59, ysize - 4);
draw_rectangle(vram, xsize, COL8_848484, 59, ysize - 23, 59, ysize - 5);
draw_rectangle(vram, xsize, COL8_000000, 2, ysize - 3, 59, ysize - 3);
draw_rectangle(vram, xsize, COL8_000000, 60, ysize - 24, 60, ysize - 3);
draw_rectangle(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize - 4, ysize - 24);
draw_rectangle(vram, xsize, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize - 4);
draw_rectangle(vram, xsize, COL8_FFFFFF, xsize - 47, ysize - 3, xsize - 4, ysize - 3);
draw_rectangle(vram, xsize, COL8_FFFFFF, xsize - 3, ysize - 24, xsize - 3, ysize - 3);
char s[40];
sprintf(s, "screen x: %d, screen y: %d", binfo->scrnx, binfo->scrny);
putfont8_str(vram, xsize, 8, 8, COL8_FFFFFF, s);
while (1)
{
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00,
0xff, 0x00, 0x00,
0x00, 0xff, 0x00,
0xff, 0xff, 0x00,
0x00, 0x00, 0xff,
0x00, 0xff, 0xff,
0xff, 0x00, 0xff,
0xff, 0xff, 0xff,
0xc6, 0xc6, 0xc6,
0x84, 0x00, 0x00,
0x00, 0x84, 0x00,
0x84, 0x84, 0x00,
0x00, 0x00, 0x84,
0x84, 0x00, 0x84,
0x00, 0x84, 0x84,
0x84, 0x84, 0x84
};
set_palette(0, 15, table_rgb);
return;
}
void set_palette(int start, int end, unsigned char * rgb)
{
int i, eflags;
eflags = io_load_eflags();
io_cli();
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 draw_rectangle(unsigned char * vram, int xsize, int color, int x0, int y0, int x1, int y1)
{
int i, j;
for(i = x0; i <= x1; i++)
for(j = y0; j <= y1; j++)
vram[i + xsize * j] = color;
return;
}
void putfont8(char *vram, int xsize, int x, int y, char c, char * font)
{
int i;
char d;
for(i = 0; i < 16; i++) {
d = font[i];
if((d & 0x80) != 0) vram[(y + i) * xsize + x + 0] = c; // 0x80 = 0b10000000
if((d & 0x40) != 0) vram[(y + i) * xsize + x + 1] = c; // 0x40 = 0b01000000
if((d & 0x20) != 0) vram[(y + i) * xsize + x + 2] = c; // 0x20 = 0b00100000
if((d & 0x10) != 0) vram[(y + i) * xsize + x + 3] = c; // 0x10 = 0b00010000
if((d & 0x08) != 0) vram[(y + i) * xsize + x + 4] = c; // 0x08 = 0b00001000
if((d & 0x04) != 0) vram[(y + i) * xsize + x + 5] = c; // 0x04 = 0b00000100
if((d & 0x02) != 0) vram[(y + i) * xsize + x + 6] = c; // 0x02 = 0b00000010
if((d & 0x01) != 0) vram[(y + i) * xsize + x + 7] = c; // 0x01 = 0b00000001
}
}
void putfont8_str(char *vram, int xsize, int x, int y, char c, unsigned char * str)
{
for(;*str != 0x00; str++) {
putfont8(vram, xsize, x, y, c, font + *str * 16);
x += 8;
if(x >= xsize) { // 换行
x %= 320;
y += 16;
}
}
}

编译运行,成功显示了数值!!!

鼠标指针的显示

类似地,我们可以绘制鼠标指针。

void init_mouse_cursor8(char *mouse, char bc)
{
static char cursor[16][16] = {
"**************..",
"*OOOOOOOOOOO*...",
"*OOOOOOOOOO*....",
"*OOOOOOOOO*.....",
"*OOOOOOOO*......",
"*OOOOOOO*.......",
"*OOOOOOO*.......",
"*OOOOOOOO*......",
"*OOOO**OOO*.....",
"*OOO*..*OOO*....",
"*OO*....*OOO*...",
"*O*......*OOO*..",
"**........*OOO*.",
"*..........*OOO*",
"............*OO*",
".............***"
};
int x, y;
for (y = 0; y < 16; y++) {
for (x = 0; x < 16; x++) {
if (cursor[y][x] == '*') {
mouse[y * 16 + x] = COL8_000000;
}
if (cursor[y][x] == 'O') {
mouse[y * 16 + x] = COL8_FFFFFF;
}
if (cursor[y][x] == '.') {
mouse[y * 16 + x] = bc;
}
}
}
return;
}

真是直接绘制啊😅其中的变量bc是背景颜色(background color)的意思。如果想显示鼠标指针,还需要以下函数把缓冲区里的数据复制到显存里。

void putblock8_8(char *vram, int vxsize, int pxsize,
int pysize, int px0, int py0, char *buf, int bxsize)
{
int x, y;
for (y = 0; y < pysize; y++) {
for (x = 0; x < pxsize; x++) {
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
}
}
return;
}

此时HariMain的主要部分如下:

void HariMain(void)
{
char * vram, * mouse;
int xsize, ysize, mx, my;
struct BOOTINFO *binfo;
init_palette();
binfo = (struct BOOTINFO *) 0x0ff0;
xsize = binfo->scrnx;
ysize = binfo->scrny;
vram = binfo->vram;
mx = 152;
my = 78;
...
char s[40];
sprintf(s, "(%d, %d)", mx, my);
putfont8_str(vram, xsize, 8, 8, COL8_FFFFFF, s);
init_mouse_cursor8(mouse, COL8_008484);
putblock8_8(vram, xsize, 16, 16, mx, my, mouse, 16);
...
}

编译运行,成功输出了鼠标指针!

GDT和IDT详解

我们在前面实际上涉及了部分GDT的知识,这里详细讲一讲。GDT是全局段描述符记录表(global segment descriptor table)的缩写。为什么要设定“段”呢?直白地说,就是让每个程序的使用空间更加清晰,相互之间尽量井水不犯河水。为了表示一个段,需要有以下信息:1️⃣段的大小是多少?2️⃣段的起始地址在哪里?3️⃣段的管理属性是什么?(禁止写入,禁止执行,系统专用等)。CPU会用8个字节(64个比特)来存放这些信息,但16位段寄存器只有16个比特。因此我们可以模仿调色板的方法,先把段号存起来,再设定好段号与段的对应关系。

段号本来可以用0到65535之间的数,但是由于CPU设计的问题,段寄存器的低三位不能使用,因此只能使用0到8191之间的数。因此我们就需要8×8192=65536个字节的空间来设定段。当然啦,我们不能把它存进CPU,只能把它存在内存里,也就是GDT。

而IDT则是中断记录表(interrupt descriptor table)的简称。当CPU遇到外部变化时,会先放下手头工作去解决中断,直到解决完毕才重新开始工作。鼠标等外部设备的信号传入传出对于CPU来说就是一种外部事件。大体思路是像调色板和GDT一样,先设定0到255为中断号码,再为其适配上不同的处理函数。

总的来说,我们需要先设定GDT完成段的规划任务,再通过IDT设定鼠标的响应函数。

// 新添加的结构体
struct SEGMENT_DESCRIPTOR {
short limit_low, base_low;
char base_mid, access_right;
char limit_high, base_high;
};
struct GATE_DESCRIPTOR {
short offset_low, selector;
char dw_count, access_right;
short offset_high;
};
// 新添加的函数
void init_gdtidt(void)
{
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) 0x0026f800;
int i;
for (i = 0; i < 8192; i++) {
set_segmdesc(gdt + i, 0, 0, 0);
}
set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);
set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);
load_gdtr(0xffff, 0x00270000);
for (i = 0; i < 256; i++) {
set_gatedesc(idt + i, 0, 0, 0);
}
load_idtr(0x7ff, 0x0026f800);
return;
}
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
if (limit > 0xfffff) {
ar |= 0x8000; /* G_bit = 1 */
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = ar & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
gd->offset_low = offset & 0xffff;
gd->selector = selector;
gd->dw_count = (ar >> 8) & 0xff;
gd->access_right = ar & 0xff;
gd->offset_high = (offset >> 16) & 0xffff;
return;
}

我们看到,两种描述符都是8字节的(回忆C语言类型知识),其中包含了段的大小、访问级别等信息。初始化的工作主要是在init_gdtidt里完成的,我们以0x0027000开始的内存空间为段空间,而0x0026f8000x0026ffff之间的256个字节是留给中断描述表的。

在GDT初始化时,我们每八个字节用set_segmdesc进行一次设定,其上限、基址和访问权限都设置为了0。随后我们指定了1号段和2号段,分别代表CPU所能管理的全部内存和为bootpack.hrb预留的区域。利用2号段,就可以执行bootpack.hrb

中间我们用到了load_gdtrload_idtr两个函数,这些都是在naskfunc.nas里新添加的函数,只是把汇编里特有的指令包装了一下。因此,我们必须更新一下naskfunc.nas

[FORMAT "WCOFF"] ; 制作目标文件的格式
[INSTRSET "i486p"] ; 使用到486为止的指令
[BITS 32] ; 制作32位模式对应的机械语言
[FILE "naskfunc.nas"] ; 源文件名
GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt
GLOBAL _io_in8, _io_in16, _io_in32
GLOBAL _io_out8, _io_out16, _io_out32
GLOBAL _io_load_eflags, _io_store_eflags
GLOBAL _load_gdtr, _load_idtr
[SECTION .text] ; 以下是函数本体
_io_hlt:
HLT
RET
_io_cli:
CLI
RET
_io_sti:
STI
RET
_io_stihlt:
STI
HLT
RET
_io_in8:
MOV EDX, [ESP+4]
MOV EAX, 0
IN AL, DX
RET
_io_in16:
MOV EDX, [ESP+4]
MOV EAX, 0
IN AX, DX
RET
_io_in32:
MOV EDX, [ESP+4]
MOV EAX, 0
IN EAX, DX
RET
_io_out8:
MOV EDX, [ESP+4]
MOV AL, [ESP+8]
OUT DX, AL
RET
_io_out16:
MOV EDX, [ESP+4]
MOV AX, [ESP+8]
OUT DX, AX
RET
_io_out32:
MOV EDX, [ESP+4]
MOV EAX, [ESP+8]
OUT DX, EAX
RET
_io_load_eflags:
PUSHFD
POP EAX
RET
_io_store_eflags:
MOV EAX, [ESP+4]
PUSH EAX
POPFD
RET
_load_gdtr:
MOV AX,[ESP+4]
MOV [ESP+6],AX
LGDT [ESP+6]
RET
_load_idtr:
MOV AX,[ESP+4]
MOV [ESP+6],AX
LIDT [ESP+6]
RET

注意⚠️汇编语言写函数也要在前面加上函数声明(GLOBAL一行)。有的读者会问,为什么是ESP+6而不是ESP+8?这涉及到LGDT和LIDT设计原理,它们只能读取6个字节的信息,它们的低2字节储存了段上限(等于有效字节数-1),高4字节代表GDT的开始地址。因此,我们把[ESP+4]处的limit变量读到[ESP+6]去,这样从[ESP+6]往后的6个字节就是我们想传入LGDT的数据。

最后我们来重点看一下set_segmdesc函数。

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
if (limit > 0xfffff) {
ar |= 0x8000; /* G_bit = 1 */
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = ar & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}

注意看其中用到了多次与运算符&,仔细思考后不难发现,0xffff是四个字节全部由1组成的,而0xff仅有两个字节全部是1,因此和它们进行与运算就相当于拿到指定字节以内的数据(1 & 1 = 1, 1 & 0 = 0),其他位全部为0。之所以将段的地址分为了low(两个字节),mid(一个字节),high(一个字节)三段,是想兼容80286操作系统,不再赘言。

仔细数一数,段的大小最大是4GB,即32位数值,本身占用4个字节,加上地址4个字节,一共8个字节,早就把结构体撑爆了。因此,我们的段上限只能指定到20位,即1MB。不着急,CPU设计者安排了一个标志位Gbit,如果该位是1,则将limit的单位解释成4KB,如此一来就可以指定4GB了!

现在结构体还剩下12位空间,我们赋予其“段属性”的地位,全称为“段的访问属性(access_right)”,通常用ar表示。其高4位被储存在limit_high的高4位里 ,而低8位在ar里。一般来说,我们只需要用到下面几种权限:

就这样,我们把段也设置好了!编译运行一下,嗯,一切都没有变,但是成功运行了!

我们明天会简单地将代码重构一下,进而开启我们的移动鼠标之路。

posted on   溴锑锑跃迁  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示