7 增加命令行窗口(3)(harib22g)
为什么程序会无法正常关闭呢?一开始笔者以为问题出在关闭窗口的函数,或者是处理程序结束的部分,但事实并非如此,这个失误比想象中更加严重。问题的原因在于应用程序的内存段消失了,突然间竟然发生这种事情,QEMU肯定也被整糊涂了。
也许大家不明白应用程序的内存段消失是怎么一回事,总之,问题出在cmd_app身上。
harib22f的cmd_app节选
set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60);
set_segmdesc(gdt + 1004, segsiz - 1, (int) q, AR_DATA32_RW + 0x60);
(中略)
start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0));
上面这段代码是用来创建应用程序段并启动应用程序的,大家仔细思考一下这段代码。
首先,color.hrb在某个窗口中被运行,启动程序一切顺利,然后显示窗口并绘图,接下来等待键盘输入并进入休眠状态。到这里为止没有任何问题。
然后我们在另外一个窗口中运行color.hrb,程序也顺利启动了,显示窗口并绘图,随后进入休眠状态。然而在这个时候,问题其实已经发生了。这是怎么回事呢?因为我们为color.hrb准备的1003号代码段和1004号数据段,被color2.hrb所用的段给覆盖掉了。
因此,当按下回车键唤醒color.hrb时,就会发生异常情况——明明应该去运行color.hrb的,结果却错误地运行了color2.hrb,这样当然会出错了。
■■■■■
既然问题的原因想明白了,要干掉这个bug也就不难了,只要为color.hrb和color2.hrb分配编号不同的段就可以了。
本次的console.c节选
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{
(中略)
if (finfo != 0) {
(中略)
if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
(中略)
set_segmdesc(gdt + task->sel / 8 + 1000, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60);
set_segmdesc(gdt + task->sel / 8 + 2000, segsiz - 1, (int) q, AR_DATA32_RW + 0x60);
(中略)
start_app(0x1b, task->sel + 1000 * 8, esp, task->sel + 2000 * 8, &(task->tss.esp0));
(中略)
} else {
(中略)
}
(中略)
}
(中略)
}
在task—>sel中填入TSS的段号 * 8(请参照mtask.c的task_init),将这个值除以8,结果一定落在3~1002。将其加上1000,就得到1003~2002的值,我们把它用作应用程序用的代码段编号;将其加上2000,即得到2003~3002的值,我们把它用作应用程序用的数据段编号。这样一来,就不会发生段被覆盖的问题了。
■■■■■
我们来试试看能不能成功,“make run”,运行color.hrb和color2.hrb,并排对比一下,然后按下回车键结束程序。啊,这次终于成功了,撒花!
成功结束了应用程序