《30天自制作業系統》讀書筆記Day19
阿新 • • 發佈:2019-01-26
GitHub地址:https://github.com/scusjs/
回憶前面的FILEINFO結構體,其中clustno表示檔案從磁碟上哪個扇區開始存放。
通過觀察系統檔案發現如下規律:
磁碟映象中的地址 = clustno * 512 + 0x003e00
接著就開始實現函數了。
先新增一個指標:
char *p;
然後具體實現命令:
前面的程式雖然能夠顯示檔案內容了,但是對於大於一個扇區(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。
開始寫程式碼:
3.程式碼整理
4.第一個應用程式
現在開始嘗試編寫第一個應用程式。試試第三天的那個程式:
將其編譯,並在Makefile中將其編譯進入系統。
然後在console.c中對其進行支援:
1.cat(type)命令
前面實現列出檔案目錄命令,這裡該實現顯示檔案內容命令了,即cat(windows下為type)。回憶前面的FILEINFO結構體,其中clustno表示檔案從磁碟上哪個扇區開始存放。
通過觀察系統檔案發現如下規律:
磁碟映象中的地址 = clustno * 512 + 0x003e00
接著就開始實現函數了。
先新增一個指標:
char *p;
然後具體實現命令:
2.FAT的支援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); }
前面的程式雖然能夠顯示檔案內容了,但是對於大於一個扇區(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中對其進行支援:
執行系統,然後在命令列中輸入hlt,發現命令列卡死,說明程式正確執行。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); }