4 结束应用程序(harib17d)

照现在这个样子,应用程序结束之后会执行HLT,我们就无法在命令行窗口中继续输入命令了,这多无聊啊。如果应用程序结束后不执行HLT,而是能返回操作系统就好了。

怎样才能实现这样的设想呢?没错,只要将应用程序中的HLT改成RET,就可以返回了。相应地,操作系统这边也需要用CALL来代替JMP启动应用程序才对。虽说是CALL,不过因为要调用的程序位于不同的段,所以实际上应该使用far-CALL,因此应用程序那边也应该使用RETF。好,我们的方针已经明确了。

■■■■■

C语言中没有用来执行far-CALL的命令,我们只好来创建一个farcall函数,这个函数和farjmp大同小异。

本次的naskfunc.nas节选

  1. _farcall: ; void farcall(int eip, int cs);
  2. CALL FAR [ESP+4] ; eip, cs
  3. RET

然后,我们还要把hlt命令的处理改为调用farcall。

本次的console.c节选

  1. void cmd_hlt(struct CONSOLE *cons, int *fat)
  2. {
  3. (中略)
  4. if (finfo != 0) {
  5. /*找到文件的情况*/
  6. (中略)
  7. farcall(0, 1003 * 8); /*这里!*/
  8. (中略)
  9. } else {
  10. /*没有找到文件的情况*/
  11. (中略)
  12. }
  13. (中略)
  14. }

最后我们还要改写一下应用程序hlt.nas,把HLT换成RETF就可以了。

本次的hlt.nas(第1部分)

  1. [BITS 32]
  2. MOV AL,'A'
  3. CALL 2*8:0xbe3
  4. RETF

■■■■■

好,完工了哦。我们来“make run”一下,然后运行“hlt”。

咦?qemu.exe又停止响应了,貌似是有bug(今天我们碰了好几个钉子了嘛)。

怎么回事呢?啊,明白了。由于我们改写了操作系统的代码,导致_asm_cons_putchar的地址发生了变化。重新查看bootpack.map,我们发现地址变成了这样:

  1. 0x0000BE8 : _asm_cons_putchar

因此,我们把应用程序修改一下。

本次的hlt.nas(第2部分)

  1. [BITS 32]
  2. MOV AL,'A'
  3. CALL 2*8:0xbe8
  4. RETF

好,改完了,再试试看。“make run”,“hlt”,怎么样?好了!成功了!

4 结束应用程序(harib17d) - 图1

心情激动,于是运行了3次hlt

趁热打铁,我们再来个新的尝试:显示“hello”。

本次的hlt.nas(第3部分)

  1. [BITS 32]
  2. MOV AL,'h'
  3. CALL 2*8:0xbe8
  4. MOV AL,'e'
  5. CALL 2*8:0xbe8
  6. MOV AL,'l'
  7. CALL 2*8:0xbe8
  8. MOV AL,'l'
  9. CALL 2*8:0xbe8
  10. MOV AL,'o'
  11. CALL 2*8:0xbe8
  12. RETF

貌似用循环比较好呢?算了,实在太麻烦(笑)。我们运行一下试试看,结果如下。

4 结束应用程序(harib17d) - 图2

你好!

话说回来,现在这个应用程序已经和当初“hlt”这个名字完全对不上号了,看来我们得赶快给它改改名字了呢。