4 命令行API(harib25d)
typeipl.hrb看起来相当不错(尤其是可以强制结束这一点很好),我们不妨就用这个程序来替代type命令吧。首先,我们需要从命令行窗口中删除type命令。从console.c中删掉cmd_type,然后将函数cons_runcmd中用于调用cmd_type的部分也删掉。嗯,看着舒服多了(这里只是删掉几个语句,就不将代码列出来了)。
现在typeipl.hrb还只能显示ipl10.nas这个文件,而我们需要实现能任意指定文件名的功能,否则它就无法完全替代type命令。为此,我们需要在用户输入“type ipl10.nas”这样的命令时获取后面的文件名,这个功能被称为获取命令行。因此我们就要编写一个API来获取命令行。
不同的操作系统下获取命令行的形式也不尽相同,Windows的API在获取命令行时并非只返回后面的文件名部分,而是返回包含应用程序名(也就是这里的type)在内的完整命令行内容,我们就来模仿这种方式吧……其实这只是一个借口啦(笑),归根结底还是因为返回完整命令行内容的API编写起来比较简单。
获取命令行
EDX=26
EBX=存放命令行内容的地址
ECX=最多可存放多少字节
EAX=实际存放了多少字节(由操作系统返回)
对程序进行的修改不多。
本次的bootpack.h节选
struct TASK {
(中略)
char *cmdline;
};
本次的console.c节选
void console_task(struct SHEET *sheet, int memtotal)
{
(中略)
task->cons = &cons;
task->cmdline = cmdline; /*这里!*/
(中略)
}
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{
(中略)
} else if (edx == 26) {
i = 0;
for (;;) {
*((char *) ebx + ds_base + i) = task->cmdline[i];
if (task->cmdline[i] == 0) {
break;
}
if (i >= ecx) {
break;
}
i++;
}
reg[7] = i;
}
return 0;
}
好,完工了,很简单吧?将cmdline添加到struct TASK中是为了把console_task的cmdline传递给hrb_api。
■■■■■
下面我们来添加apilib的函数。
api026.nas节选
_api_cmdline: ; int api_cmdline(char *buf, int maxsize);
PUSH EBX
MOV EDX,26
MOV ECX,[ESP+12] ; maxsize
MOV EBX,[ESP+8] ; buf
INT 0x40
POP EBX
RET
然后我们来编写应用程序,就叫type.c。
type.c
#include "apilib.h"
void HariMain(void)
{
int fh;
char c, cmdline[30], *p;
api_cmdline(cmdline, 30);
for (p = cmdline; *p > ' '; p++) { } /*跳过之前的内容,直到遇到空格*/
for (; *p == ' '; p++) { } /*跳过空格*/
fh = api_fopen(p);
if (fh != 0) {
for (;;) {
if (api_fread(&c, 1, fh) == 0) {
break;
}
api_putchar(c);
}
} else {
api_putstr0("File not found.\n");
}
api_end();
}
获取命令行内容之后进行的p的计算可能不容易看明白,所以我们稍微讲解一下。
之前在命令行窗口中,我们直接指定了p = cmdline + 5;,这是为了跳过“type”直接取出用户所指定的文件名。而这次我们是通过应用程序来实现的,用户完全可能通过“type.hrb 文件名”这种形式来运行,这样一来我们就不是跳过5个字符,而是要跳过9个字符了。此外,用户也是可以改变应用程序名称的,例如可以改成像Linux那样的cat.hrb。
为了在任何情况下都能顺利运行程序,我们要逐字读取cmdline的内容,遇到比空格的字符编码大的字符连续出现时,将它们全部跳过,这样一来无论是“type”、“type.hrb”还是“cat”都可以跳过去了。
跳过应用程序名之后,还要跳过空格,然后我们就可以将文件名的部分剥离出来了。
■■■■■
我们来“make run”试试看。type.hrb的大小为256字节,还是相当小的,不错(如果用汇编语言编写的话,应该还能更小吧)。运行也很成功,而且由于这是一个应用程序,还可以在中途强制结束,撒花!
type ipl10.nas
运行“type ipll0.nas”时的情形
另外,由于去掉了type命令的功能,操作系统核心的haribote.sys也从原来的33871字节减少到了33716字节。由于添加了新的API,所以只减少了155字节,不过整体上还是稍微变小了一点,也不错啦!