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节选

  1. struct TASK {
  2. (中略)
  3. char *cmdline;
  4. };

本次的console.c节选

  1. void console_task(struct SHEET *sheet, int memtotal)
  2. {
  3. (中略)
  4. task->cons = &cons;
  5. task->cmdline = cmdline; /*这里!*/
  6. (中略)
  7. }
  8. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  9. {
  10. (中略)
  11. } else if (edx == 26) {
  12. i = 0;
  13. for (;;) {
  14. *((char *) ebx + ds_base + i) = task->cmdline[i];
  15. if (task->cmdline[i] == 0) {
  16. break;
  17. }
  18. if (i >= ecx) {
  19. break;
  20. }
  21. i++;
  22. }
  23. reg[7] = i;
  24. }
  25. return 0;
  26. }

好,完工了,很简单吧?将cmdline添加到struct TASK中是为了把console_task的cmdline传递给hrb_api。

■■■■■

下面我们来添加apilib的函数。

api026.nas节选

  1. _api_cmdline: ; int api_cmdline(char *buf, int maxsize);
  2. PUSH EBX
  3. MOV EDX,26
  4. MOV ECX,[ESP+12] ; maxsize
  5. MOV EBX,[ESP+8] ; buf
  6. INT 0x40
  7. POP EBX
  8. RET

然后我们来编写应用程序,就叫type.c。

type.c

  1. #include "apilib.h"
  2. void HariMain(void)
  3. {
  4. int fh;
  5. char c, cmdline[30], *p;
  6. api_cmdline(cmdline, 30);
  7. for (p = cmdline; *p > ' '; p++) { } /*跳过之前的内容,直到遇到空格*/
  8. for (; *p == ' '; p++) { } /*跳过空格*/
  9. fh = api_fopen(p);
  10. if (fh != 0) {
  11. for (;;) {
  12. if (api_fread(&c, 1, fh) == 0) {
  13. break;
  14. }
  15. api_putchar(c);
  16. }
  17. } else {
  18. api_putstr0("File not found.\n");
  19. }
  20. api_end();
  21. }

获取命令行内容之后进行的p的计算可能不容易看明白,所以我们稍微讲解一下。

之前在命令行窗口中,我们直接指定了p = cmdline + 5;,这是为了跳过“type”直接取出用户所指定的文件名。而这次我们是通过应用程序来实现的,用户完全可能通过“type.hrb 文件名”这种形式来运行,这样一来我们就不是跳过5个字符,而是要跳过9个字符了。此外,用户也是可以改变应用程序名称的,例如可以改成像Linux那样的cat.hrb。

为了在任何情况下都能顺利运行程序,我们要逐字读取cmdline的内容,遇到比空格的字符编码大的字符连续出现时,将它们全部跳过,这样一来无论是“type”、“type.hrb”还是“cat”都可以跳过去了。

跳过应用程序名之后,还要跳过空格,然后我们就可以将文件名的部分剥离出来了。

■■■■■

我们来“make run”试试看。type.hrb的大小为256字节,还是相当小的,不错(如果用汇编语言编写的话,应该还能更小吧)。运行也很成功,而且由于这是一个应用程序,还可以在中途强制结束,撒花!

4 命令行API(harib25d) - 图1

type ipl10.nas

运行“type ipll0.nas”时的情形

另外,由于去掉了type命令的功能,操作系统核心的haribote.sys也从原来的33871字节减少到了33716字节。由于添加了新的API,所以只减少了155字节,不过整体上还是稍微变小了一点,也不错啦!