5 第一个应用程序(harib16e)
好,既然现在我们已经可以读取文件的内容,那么运行应用程序也就不难实现了。
作为头一次尝试,我们要挑战什么样的应用程序呢?当然还是从简单的开始啦。唔,最简单的应用程序是……到底哪个比较好呢?哦,有了,就选那个吧。
因此,请大家把书一口气翻回到3.5节,那里有一个非常简单的操作系统程序,只有3个字节。可能有些人连翻书都懒得翻,好吧,我们就再次来个那3个字节程序的大公开吧!(笑)
3个字节的应用程序
[BITS 32]
fin:
HLT
JMP fin
将上面这段代码保存为hlt.nas,然后用nask进行汇编,生成hlt.hrb。可能大家会问,这个扩展名.hrb是啥?这个嘛,其实是haribote的缩写。如果我们命名为.exe文件的话,就会和Windows的可执行文件产生混淆,因此这里我们用了个自定义的扩展名。
■■■■■
那么,要怎样才能运行文件的内容呢?像type命令一样,我们用file_loadfile将文件的内容读到内存中,问题是后面要怎么办?
应用程序不知道自己被读到哪个内存地址,这里暂且由ORG 0来生成。因此,为了应用程序能够顺利运行,我们需要为其创建一个内存段。
段创建好之后,接下来只要goto到该段中的程序,程序应该就会开始运行了。要goto到其他的内存段,在汇编语言中用farjmp指令。话说,这个指令我们在任务切换的时候已经用过了嘛。因此,这次我们不需要改动naskfunc.nas中的函数就可以运行hlt.hrb了,撒花。
■■■■■
写好的程序如下。
本次的console.c节选
void console_task(struct SHEET *sheet, unsigned int memtotal)
{
(中略)
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
(中略)
for (;;) {
io_cli();
if (fifo32_status(&task->fifo) == 0) {
(中略)
} else {
(中略)
if (256 <= i && i <= 511) { /*键盘数据(通过任务A) */
if (i == 8 + 256) {
(中略)
} else if (i == 10 + 256) {
(中略)
if (strcmp(cmdline, "mem") == 0) {
(中略)
} else if (strcmp(cmdline, "cls") == 0) {
(中略)
} else if (strcmp(cmdline, "dir") == 0) {
(中略)
} else if (strncmp(cmdline, "type ", 5) == 0) {
(中略)
} else if (strcmp(cmdline, "hlt") == 0) {
/*从此开始*/ /*启动应用程序hlt.hrb */
for (y = 0; y < 11; y++) {
s[y] = ' ';
}
s[0] = 'H';
s[1] = 'L';
s[2] = 'T';
s[8] = 'H';
s[9] = 'R';
s[10] = 'B';
for (x = 0; x < 224; ) {
if (finfo[x].name[0] == 0x00) {
break;
}
if ((finfo[x].type & 0x18) == 0) {
for (y = 0; y < 11; y++) {
if (finfo[x].name[y] != s[y]) {
goto hlt_next_file;
}
}
break; /*找到文件*/
}
hlt_next_file:
x++;
}
if (x < 224 && finfo[x].name[0] != 0x00) {
/*找到文件的情况*/
p = (char *) memman_alloc_4k(memman, finfo[x].size);
file_loadfile(finfo[x].clustno, finfo[x].size, p, fat, (char *)
(ADR_DISKIMG + 0x003e00));
set_segmdesc(gdt + 1003, finfo[x].size - 1, (int) p, AR_CODE32_ER);
farjmp(0, 1003 * 8);
memman_free_4k(memman, (int) p, finfo[x].size);
} else {
/*没有找到文件的情况*/
putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, "File not found.", 15);
cursor_y = cons_newline(cursor_y, sheet);
}
/*到此结束*/ cursor_y = cons_newline(cursor_y, sheet);
} else if (cmdline[0] != 0) {
(中略)
}
(中略)
} else {
(中略)
}
}
(中略)
}
}
}
这次添加的hlt命令,是用来启动hlt.hrb这个应用程序的,前半部分和type命令的代码非常类似。
hlt.hrb成功读入内存之后,将其注册为GDT的1003号。为什么要用1003号呢?100号或者12号不行吗?还真不行,因为1~2号由dsctbl.c使用,而3~1002号由mtask.c使用,所以我们用了1003号,因此如果把1003号换成1234号之类的还是没问题的哦。
随后,当内存段创建完成后,用farjmp跳转并运行。
■■■■■
我们来试试看吧,“make run”,然后在命令行窗口中运行hlt命令,这是“纸娃娃系统”历史上首次运行应用程序,我们的心情无比激动。咦?程序停止了。
运行时的样子
糟糕,难道是bug?转念一想,这个程序本来就是执行HTL,这样才是正常的嘛。因为程序不会执行任何操作,因此看上去好像是停止了一样。对了,其实(看上去)停止了的只有命令行窗口而已,如果按下Tab键的话,还是可以切换回task_a的哦。
唔,不过这样一来,我们就没办法判断命令行窗口的停止到底是因为运行了hlt.hrb呢,还是由于另外一些原因不明的bug导致的。我们还是要再确认一下才行。
该怎么办呢?我们用个巧办法吧:
改造版的第一个应用程序
[BITS 32]
CLI
fin:
HLT
JMP fin
我们在开头加上了一个CLI指令,这样整个程序变成了4个字节。如果应用程序正常运行的话,中断处理会被禁止,因此即便按下Tab键也无法切换回task_a,鼠标应该也停止不动了。
那么我们来试验一下。哇,真的停止了耶!太棒了,果然我们的应用程序成功运行了。话说回来,冷静下来一想,自己制作的操作系统明明死机了却还开心得不得了,真是个奇怪的家伙(笑)。总之,撒花。
好了,今天的内容就到这里。明天我们继续加油哦!