6 增加命令行窗口(2)(harib22f)

到底应该改哪里呢?其实笔者已经心里有数了,函数hrb_api()中的这句:

  1. struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);

应该就是问题所在了,这里的cons变量是用来判断“要向哪个命令行窗口输出字符”的关键。该变量的值是从内存地址0x0fec读取出来的,而无论从哪个任务读取这个内存地址中的值,得到的肯定都是同一个值,因此不管在哪个窗口中运行a.hrb,都只能在固定的其中一个窗口中显示字符。

6 增加命令行窗口(2)(harib22f) - 图1

harib22e中,无论在哪个窗口运行,结果都一样

那么该如何解决这个问题呢?嗯,看看这种方法怎么样。

本次的bootpack.h节选

  1. struct TASK {
  2. int sel, flags; /* sel代表GDT编号*/
  3. int level, priority;
  4. struct FIFO32 fifo;
  5. struct TSS32 tss;
  6. struct CONSOLE *cons; /*从此开始*/
  7. int ds_base; /*到此结束*/
  8. };

每个任务都拥有各自的TASK结构,只要我们将cons保存在TASK结构中,就可以由不同的任务读取出不同的值了。此外,我们将ds_base也放到了TASK结构中,理由和上面的cons是相同的。ds_base之前是从内存地址0x0fe8处读取的,但很明显,cons[0]的应用程序数据段地址和cons[1]的地址肯定是不同的,如果不在这里区分开的话,字符串的显示就会出问题。

■■■■■

接下来我们只要将代码中的((int ) 0x0fec)和((int ) 0x0fe8)全部改为使用TASK结构中的cons和ds_base成员就可以了,需要修改的只有console.c一个文件。

本次的console.c节选

  1. void console_task(struct SHEET *sheet, int memtotal)
  2. {
  3. (中略)
  4. task->cons = &cons; /*修改前:*((int *) 0x0fec) = (int) &cons;*/
  5. (中略)
  6. }
  7. int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
  8. {
  9. (中略)
  10. if (finfo != 0) {
  11. (中略)
  12. if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
  13. (中略)
  14. task->ds_base = (int) q; /*修改前:*((int *) 0x0fe8) = (int) &q;*/
  15. } else {
  16. (中略)
  17. }
  18. (中略)
  19. }
  20. (中略)
  21. }
  22. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  23. {
  24. (中略)
  25. int ds_base = task->ds_base; /*这里!*/
  26. struct CONSOLE *cons = task->cons; /*这里!*/
  27. (中略)
  28. }
  29. int *inthandler0c(int *esp)
  30. {
  31. (中略)
  32. struct CONSOLE *cons = task->cons; /*这里!*/
  33. (中略)
  34. }
  35. int *inthandler0d(int *esp)
  36. {
  37. (中略)
  38. struct CONSOLE *cons = task->cons; /*这里!*/
  39. (中略)
  40. }

好,完工啦。现在无论在哪个窗口运行a.hrb,应该会在相应的窗口中显示出字符……了吧……

■■■■■

我们来试验一下吧。“make run”,在两边的窗口分别运行a.hrb!哦哦,成功了,太棒了!(要是这样还不行的话,笔者真的不知道该怎么办了,小捏了一把汗)

6 增加命令行窗口(2)(harib22f) - 图2

a.hrb运行成功!

趁热打铁,我们来运行color.hrb和color2.hrb试试看。哇!成功了!现在我们可以把两个窗口并排对比了,终于实现了当初的夙愿。

6 增加命令行窗口(2)(harib22f) - 图3

color.hrb vs color2.hrb

接下来我们来做点别的试验吧,比如说把color.hrb和color2.hrb的窗口关闭(注:Shift+F1和“×”按钮点击的处理我们还没有改好,记得按回车键退出程序哦)……咦?哐叽,QEMU出错退出了1

1 这是由于color.hrb和color2.hrb的启动顺序、各从哪个命令行窗口运行的、以及先关闭的哪一个窗口等不同情况导致的,出错的方式貌似也不一样。应用程序没有bug,也没有故意捣乱,这是由于“纸娃娃系统”本身所引发的异常。

因此,在两个color程序PK之后,我们的下一个目标就是要使窗口能够正常关闭。