自制作業系統Antz day11——實現shell(下)命令響應
阿新 • • 發佈:2018-12-15
我已經規範了系統程式碼風格,類似於按照linux分包,把各部分功能區分開了
在之前的任務中,我們已經通過直接操作顯示卡驅動完成了簡單的圖形化。
需要了解之前的部分:
直接操作顯示卡請參考day03
簡單圖形化的實現請參考day09
鍵盤按鍵中斷響應請參考day10
Makefile
專案目錄
一 . 如何實現命令快取
在之前已經完成了鍵盤的響應工作,但這種響應卻是有很大的問題,比如說對於一次按鍵的兩次中斷處理。後來我把兩種中斷都加入了響應判斷中,這樣就不會有之前第10天所提到的bug了。
* 在替換函式中完成識別。修改如下
char* replace_char(char s[40]){ char *chr = "$" ; if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){ chr = "a" ; }else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){ chr = "b" ; } ... // 省略 return chr ;
* 這裡是一些功能按鍵的識別修改
// Enter -> 回車鍵 響應之前快取的命令 換行 if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){ action_command(binfo); //響應命令 write_x = 58 ; //下面是換行 write_y += 19 ; putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); } // F1 -> 終端重新整理 類似於clear命令 else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){ //關於F1的響應中斷 sprintf(command,"%s",""); // 命令快取清空 flag = 0 ; // 按鍵模式回覆預設,這個看第10天,本質目的是為了處理一次按鍵的兩次終端 new_pe(binfo); // 通過操作視訊記憶體直接重新整理當前終端 putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); } // Backspace -> 刪格鍵 else if(strcmp(s,"0E")==0){ // 回退 write_x -= 8 ; boxfill8(binfo->vram, binfo->scrnx , COL8_000000, write_x, write_y, write_x+19, write_y+19); if(write_x<=58){ write_x = 146 ; write_y -= 19 ; } }
這些就是按鍵識別上目前修改的內容了。
接下來我們要新增一個功能,在每次按鍵之後,不但在螢幕上顯示這個鍵,而且將他快取在緩衝區,在下次回車的時候進行識別,並清空。
先來看一個簡單的demo
// command陣列就是命令快取區
char command[100] = "";
void add_command(char *s) {
sprintf(command,"%s%s",command,s);
}
void action_command(){
// 響應
}
二 . 實現
command就是一個命令快取陣列,每次按鍵之後呼叫add_command()命令將這次的按鍵儲存。
sprintf()這個函式是字串格式化命令,主要功能是把格式化的資料寫入某個字串中。sprintf 是個變參函式。使用sprintf 對於寫入buffer的字元數是沒有限制的,這就存在了buffer溢位的可能性。
我們使用sprintf函式直接在command後面添加了s字元。
那麼在下次按下Enter的時候,我們只需要呼叫action_command,並且在裡面識別是什麼命令,然後做出合適的響應即可。
來看看完整的命令緩衝區實現。
// 指令快取,但是因為中斷響應的時間問題,終端輸入速度要非常慢
char command[100] = "";
void add_command(char *s) {
if(strcmp(s," ")==0){
sprintf(command,"%s%s",command,"");
}else if(strcmp(s,"$")){
//忽略這種錯誤輸入
}else {
sprintf(command,"%s%s",command,s);
}
}
void action_command(struct BOOTINFO *binfo){
// action command 響應命令
// ls命令
// data命令
if(strcmp(command,"data")==0){
// get new data;
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018");
}else if(strcmp(command,"cls")==0){
flag = 0 ;
new_pe(binfo);
}else if(strcmp(command,"version")==0){
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1");
}else if(strcmp(command,"help")==0){
// help內容過多,顯示在圖形化介面區域
}else if(sizeof(command)>=1){
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found");
}
// 命令快取清除
sprintf(command,"%s","");
}
現在使用Makefile來生成這個支援命令的img映象。
make img
使用虛擬機器開啟映象,結果如下
終端主要程式碼如下:
int write_x = 55 ;
int write_y = 57 ;
char* replace_char(char s[40]){
char *chr = "$" ;
if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){
chr = "a" ;
}else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){
chr = "b" ;
}else if((strcmp(s,"2E")==0)||(strcmp(s,"AE")==0)){
chr = "c" ;
}else if((strcmp(s,"20")==0)||(strcmp(s,"A0")==0)){
chr = "d" ;
}else if((strcmp(s,"12")==0)||(strcmp(s,"92")==0)){
chr = "e" ;
}else if((strcmp(s,"21")==0)||(strcmp(s,"A1")==0)){
chr = "f" ;
}else if((strcmp(s,"22")==0)||(strcmp(s,"A2")==0)){
chr = "g" ;
}else if((strcmp(s,"23")==0)||(strcmp(s,"A3")==0)){
chr = "h" ;
}else if((strcmp(s,"17")==0)||(strcmp(s,"97")==0)){
chr = "i" ;
}else if((strcmp(s,"24")==0)||(strcmp(s,"A4")==0)){
chr = "j" ;
}else if((strcmp(s,"25")==0)||(strcmp(s,"A5")==0)){
chr = "k" ;
}else if((strcmp(s,"26")==0)||(strcmp(s,"A6")==0)){
chr = "l" ;
}else if((strcmp(s,"32")==0)||(strcmp(s,"B2")==0)){
chr = "m" ;
}else if((strcmp(s,"31")==0)||(strcmp(s,"B1")==0)){
chr = "n" ;
}else if((strcmp(s,"18")==0)||(strcmp(s,"98")==0)){
chr = "o" ;
}else if((strcmp(s,"19")==0)||(strcmp(s,"99")==0)){
chr = "p" ;
}else if((strcmp(s,"10")==0)||(strcmp(s,"90")==0)){
chr = "q" ;
}else if((strcmp(s,"13")==0)||(strcmp(s,"93")==0)){
chr = "r" ;
}else if((strcmp(s,"1F")==0)||(strcmp(s,"9F")==0)){
chr = "s" ;
}else if((strcmp(s,"14")==0)||(strcmp(s,"94")==0)){
chr = "t" ;
}else if((strcmp(s,"16")==0)||(strcmp(s,"96")==0)){
chr = "u" ;
}else if((strcmp(s,"2F")==0)||(strcmp(s,"AF")==0)){
chr = "v" ;
}else if((strcmp(s,"11")==0)||(strcmp(s,"91")==0)){
chr = "w" ;
}else if((strcmp(s,"2D")==0)||(strcmp(s,"AD")==0)){
chr = "x" ;
}else if((strcmp(s,"15")==0)||(strcmp(s,"95")==0)){
chr = "y" ;
}else if((strcmp(s,"2C")==0)||(strcmp(s,"AC")==0)){
chr = "z" ;
}else if((strcmp(s,"39")==0)||(strcmp(s,"B9")==0)){
chr = " " ;
}
return chr ;
}
int flag = 1 ;
// 指令快取,但是因為中斷響應的時間問題,終端輸入速度要非常慢
char command[100] = "";
void add_command(char *s) {
/*
if(strcmp(s," ")==0){
sprintf(command,"%s%s",command,"");
}else if(strcmp(s,"$")){
//忽略這種錯誤輸入
}else {
}
*/
sprintf(command,"%s%s",command,s);
}
void action_command(struct BOOTINFO *binfo){
// action command
// ls
// data
if(strcmp(command,"data")==0){
// get new data;
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018");
}else if(strcmp(command,"cls")==0){
flag = 0 ;
new_pe(binfo);
}else if(strcmp(command,"version")==0){
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1");
}else if(strcmp(command,"help")==0){
// help內容過多,顯示在圖形化介面區域
}else if(sizeof(command)>=1){
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found");
}
// 命令快取清除
sprintf(command,"%s","");
}
void key(struct BOOTINFO *binfo,char s[40]){
if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){
action_command(binfo);
write_x = 58 ;
write_y += 19 ;
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
}else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){ //關於F1的響應中斷
sprintf(command,"%s","");
flag = 0 ;
new_pe(binfo);
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
}else if(strcmp(s,"0E")==0){
// 回退
write_x -= 8 ;
boxfill8(binfo->vram, binfo->scrnx , COL8_000000, write_x, write_y, write_x+19, write_y+19);
if(write_x<=58){
write_x = 146 ;
write_y -= 19 ;
}
}else {
//putfonts8_asc(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, s);
putfonts8_asc(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, replace_char(s));
add_command(replace_char(s));
write_x += 8 ;
// 新增響應區
//清除
//boxfill8(binfo->vram, binfo->scrnx, COL8_008400 , 300 ,240 ,310 ,250);
//列印字元 Only use debug
//putfonts8_asc(binfo->vram, binfo->scrnx, 300, 240 ,COL8_000000, s) ;
}
if(write_x>148){
write_x = 58 ;
write_y += 19 ;
//putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>");
}
if(write_y>180){
new_pe(binfo);
putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
}
}
void main(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
char s[40], mcursor[256], keybuf[32], mousebuf[128];
int mx, my, i;
init_gdtidt();
init_pic();
io_sti(); /* PIC的初始化已經完成*/
fifo8_init(&keyfifo, 32, keybuf);
fifo8_init(&mousefifo, 128, mousebuf);
io_out8(PIC0_IMR, 0xf9); /* 開放PIC1和鍵盤中斷(11111001) */
io_out8(PIC1_IMR, 0xef); /* 開放滑鼠中斷(11101111) */
init_keyboard();
init_palette();
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz");
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz");
putfonts8_asc(binfo->vram, binfo->scrnx, 107, 0, COL8_000000, "|-|o|x|");
putfonts8_asc(binfo->vram, binfo->scrnx, 4, 19, COL8_FFFFFF, "AntzOS> SayHello()");
putfonts8_asc(binfo->vram, binfo->scrnx, 4, 38, COL8_FFFFFF, "Hello My AntzOs.");
putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>_");
for (;;) {
io_cli();
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
io_stihlt();
} else {
if (fifo8_status(&keyfifo) != 0) {
i = fifo8_get(&keyfifo);
io_sti();
sprintf(s, "%02X", i);
if (flag){
key(binfo,s);
}
if(flag==1){
flag = 0 ;
}else {
flag = 1 ;
}
}
}
}
}
void new_pe(struct BOOTINFO *binfo){
write_x = 58 ;
write_y = 19 ;
// 右邊並沒有儲存
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz");
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz");
putfonts8_asc(binfo->vram, binfo->scrnx, 107, 0, COL8_000000, "|-|o|x|");
// 此處保留此輸出,交給呼叫者自己
// putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>");
}