您的位置:首页 > 其它

《30天自制操作系统》读书笔记Day19

2013-11-21 16:57 239 查看
GitHub地址:https://github.com/scusjs/

1.cat(type)命令

前面实现列出文件目录命令,这里该实现显示文件内容命令了,即cat(windows下为type)。

回忆前面的FILEINFO结构体,其中clustno表示文件从磁盘上哪个扇区开始存放。

通过观察系统文件发现如下规律:

磁盘镜像中的地址 = clustno * 512 + 0x003e00

接着就开始实现函数了。

先添加一个指针:

char *p;

然后具体实现命令:

else if ((strncmp(cmdline,"cat ",4) == 0) || (strncmp(cmdline,"type ",5) == 0))
{
//准备文件名
for (y = 0; y < 11; y++)
{
s[y] = ' ';
}
y = 0;
if (strncmp(cmdline,"cat ",4) == 0)
{
x = 4;
}
else
{
x = 5;
}
for (; y < 11 && cmdline[x] != 0; x++)
{
if (cmdline[x] == '.' && y <= 8)
{
y = 8;
}
else
{
s[y] = cmdline[x];
if ('a' <= s[y] && s[y] <= 'z')//全部转换为大写
{
s[y] -= 0x20;
}
y++;
}
}
//寻找文件
for (x = 0; x < 224; x++)
{
if (finfo[x].name[0] == 0x00)
{
break;
}
if ((finfo[x].type & 0x18) == 0)
{
for (y = 0; y < 11; y ++)
{
if (finfo[x].name[y] != s[y])
{
break;
}
}
if (y >= 11)
break;//找到文件
}
}
if (x < 244 && finfo[x].name[0] != 0x00)
{
y = finfo[x].size;
p = (char *) (finfo[x].clustno * 512 + 0x003e00 + ADR_DISKIMG);
cursor_x = 8;
for (x = 0; x < y; x++)//逐字输出
{
s[0] = p[x];
s[1] = 0;
if (s[0] == 0x09)//制表符
{
for (;;)
{
putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
cursor_x += 8;
if (cursor_x == 8 + 240)
{
cursor_x = 8;
cursor_y = cons_newline(cursor_y, sheet);
}
if (((cursor_x - 8) & 0x1f) == 0)	//被32整除则break
{
break;
}
}
}
else if (s[0] == 0x0a)//换行
{
cursor_x = 8;
cursor_y = cons_newline(cursor_y, sheet);
}
else if (s[0] == 0x0d)//回车
{

}
else
{
putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, s, 1);
cursor_x += 8;
if (cursor_x == 8 + 240)
{
cursor_x = 8;
cursor_y = cons_newline(cursor_y, sheet);
}
}
}
}
else
{
putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, "File not found.", 15);
cursor_y = cons_newline(cursor_y, sheet);
}
cursor_y = cons_newline(cursor_y, sheet);
}
2.FAT的支持

前面的程序虽然能够显示文件内容了,但是对于大于一个扇区(512字节)的内容的显示还是有问题的。

在FAT(file allocation table)中,第0柱面、0磁头、2扇区开始的9个扇区(0x000200~0x0013ff)会记录大于一扇区文件的内容记录在哪些位置。

简单说下FAT:

FAT中记录下一部分内容在哪个位置。其中数据会进行处理,其实就是进行移位操作,比如磁盘上:

ab cd ef,处理后得到FAT真实数据:dab efc,其中,dab与efc分别表示数字。读文件时,例如clustno=2,读取0x004200~0x0043ff数据,接下来查看FAT第二个记录,如果其为003,则下一部分在clustno=3,即读取0x004400~0x0045ff,这样下去直到FAT中记录为FF8~FFF。

开始写代码:

int *fat = (int *) memman_alloc_4k(memman, 4*2880);
。。。
file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
。。。
if (x < 244 && finfo[x].name[0] != 0x00)
{
p = (char *) memman_alloc_4k(memman, finfo[x].size);
file_loadfile(finfo[x].clustno, finfo[x].size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
cursor_x = 8;
for (y = 0; y < finfo[x].size; y++)//逐字输出
{
...
}
...
memman_free(memman, (int) p, finfo[x].size);
}
运行即可。

3.代码整理

窗口相关函数——>window.c
命令行窗口相关函数——>console.c
文件相关函数——>file.c
在Makefile中添加相应的obj即可。

4.第一个应用程序

现在开始尝试编写第一个应用程序。试试第三天的那个程序:

[BITS 32]
fin:
HLT
JMP fin
输入命令:..\z_tools\nask.exe hlt.nas hlt.dog

将其编译,并在Makefile中将其编译进入系统。

然后在console.c中对其进行支持:

else if (strcmp(cmdline,"hlt") == 0)
{
for (y = 0; y < 11; y++)
{
s[y] = ' ';
}
s[0] = 'H';
s[1] = 'L';
s[2] = 'T';
s[8] = 'D';
s[9] = 'O';
s[10]= 'G';
for (x = 0; x < 224; x++)
{
if (finfo[x].name[0] == 0x00)
{
break;
}
if ((finfo[x].type & 0x18) == 0)
{
for (y = 0; y < 11; y ++)
{
if (finfo[x].name[y] != s[y])
{
break;
}
}
if (y >= 11)
break;//找到文件
}
}
if (x < 224 && finfo[x].name[0] != 0x00)
{
p = (char *) memman_alloc_4k(memman, finfo[x].size);
file_loadfile(finfo[x].clustno, finfo[x].size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
set_segmdesc(gdt + 1003, finfo[x].size - 1, (int) p, AR_CODE32_ER);//将其注册到GDT的1003号
farjmp(0, 1003*8);
memman_free_4k(memman, (int) p, finfo[x].size);
}
else
{
putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, "File not found.", 15);
cursor_y = cons_newline(cursor_y, sheet);
}
cursor_y = cons_newline(cursor_y, sheet);
}
运行系统,然后在命令行中输入hlt,发现命令行卡死,说明程序正确执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: