4 结束应用程序(harib17d)
照现在这个样子,应用程序结束之后会执行HLT,我们就无法在命令行窗口中继续输入命令了,这多无聊啊。如果应用程序结束后不执行HLT,而是能返回操作系统就好了。
怎样才能实现这样的设想呢?没错,只要将应用程序中的HLT改成RET,就可以返回了。相应地,操作系统这边也需要用CALL来代替JMP启动应用程序才对。虽说是CALL,不过因为要调用的程序位于不同的段,所以实际上应该使用far-CALL,因此应用程序那边也应该使用RETF。好,我们的方针已经明确了。
■■■■■
C语言中没有用来执行far-CALL的命令,我们只好来创建一个farcall函数,这个函数和farjmp大同小异。
本次的naskfunc.nas节选
_farcall: ; void farcall(int eip, int cs);
CALL FAR [ESP+4] ; eip, cs
RET
然后,我们还要把hlt命令的处理改为调用farcall。
本次的console.c节选
void cmd_hlt(struct CONSOLE *cons, int *fat)
{
(中略)
if (finfo != 0) {
/*找到文件的情况*/
(中略)
farcall(0, 1003 * 8); /*这里!*/
(中略)
} else {
/*没有找到文件的情况*/
(中略)
}
(中略)
}
最后我们还要改写一下应用程序hlt.nas,把HLT换成RETF就可以了。
本次的hlt.nas(第1部分)
[BITS 32]
MOV AL,'A'
CALL 2*8:0xbe3
RETF
■■■■■
好,完工了哦。我们来“make run”一下,然后运行“hlt”。
咦?qemu.exe又停止响应了,貌似是有bug(今天我们碰了好几个钉子了嘛)。
怎么回事呢?啊,明白了。由于我们改写了操作系统的代码,导致_asm_cons_putchar的地址发生了变化。重新查看bootpack.map,我们发现地址变成了这样:
- 0x0000BE8 : _asm_cons_putchar
因此,我们把应用程序修改一下。
本次的hlt.nas(第2部分)
[BITS 32]
MOV AL,'A'
CALL 2*8:0xbe8
RETF
好,改完了,再试试看。“make run”,“hlt”,怎么样?好了!成功了!
心情激动,于是运行了3次hlt
趁热打铁,我们再来个新的尝试:显示“hello”。
本次的hlt.nas(第3部分)
[BITS 32]
MOV AL,'h'
CALL 2*8:0xbe8
MOV AL,'e'
CALL 2*8:0xbe8
MOV AL,'l'
CALL 2*8:0xbe8
MOV AL,'l'
CALL 2*8:0xbe8
MOV AL,'o'
CALL 2*8:0xbe8
RETF
貌似用循环比较好呢?算了,实在太麻烦(笑)。我们运行一下试试看,结果如下。
你好!
话说回来,现在这个应用程序已经和当初“hlt”这个名字完全对不上号了,看来我们得赶快给它改改名字了呢。