1. 程式人生 > >自制作業系統Antz day10——實現shell(上)

自制作業系統Antz day10——實現shell(上)

我已經規範了系統程式碼風格,類似於按照linux分包,把各部分功能區分開了

在之前的任務中,我們已經通過直接操作顯示卡驅動完成了簡單的圖形化。

需要了解之前的部分:

直接操作顯示卡請參考day03

簡單圖形化的實現請參考day09

Makefile

專案目錄

s

console的圖形化實現與規則均在main/bootpack.c中完成

interrupt/int.c 中實現了鍵盤中斷處理,按鍵會中斷兩次,一次按下,一次彈起,在響應處理中,只需要處理第一次按下即可。

一 . 鍵盤按鍵

如何來判斷中斷來自於鍵盤?(程式碼如下)

    // gdt初始化操作...
    // fifo載入操作...
    if (fifo8_status(&keyfifo) != 0) {  // True則說明中斷來自於鍵盤
        i = fifo8_get(&keyfifo);
        io_sti();
        // i 就是中斷返回的值,分析他即可得到按鍵資訊, 在下面我把它轉換為了16進位制儲存在了一個char array s中
        sprintf(s, "%02X", i);
        // 把兩次中斷變為一次,看下文
    }

得到了s,就是得到了鍵盤按鍵的資訊。

開頭說了,按下一次,會有兩次中斷髮生,那麼我們是否可以使用一個flag來區分按下和彈起呢?

    if (flag){
        keyshow(); // 顯示這次按鍵,把按下的中斷當作一個鍵位的資訊,把彈起的中斷用下面flag的方法遮蔽掉
    }
    // 遮蔽
    if(flag==1){
        flag = 0 ;
    }else {
        flag = 1 ;
    }

這是一個很拙略的實現方法,而且我測試了幾次之後發現有一個bug,就是同時按下兩個鍵位時,遮蔽的方法就會變成另一種。

比如開始是用按下識別一個鍵位,那麼同時按下兩個鍵位之後就是以彈起的方法來識別鍵位了。

這個情況留在之後再考慮。

二 . 按鍵識別

上文中已經將按鍵返回的資料儲存到了char陣列s,只需要在螢幕上顯示s的資料就可以了。

int write_x = 55 ; //按鍵顯示位置的x,y座標
int write_y = 57 ;

void key(struct BOOTINFO *binfo,char s[40]){
    //在指定位置顯示資料
    showkeys(binfo->vram, binfo->scrnx,  write_x,  write_y, COL8_FFFFFF, s);
    // 顯示之後游標右移
    write_x += 19 ;
    // 如果超出右邊界,換行
    if(write_x>155){
        write_x = 55 ;
        write_y += 19 ;
    }
    // 如果超出下邊界,重新整理清理本頁,開啟新的一頁
    if(write_y>180){
        new_pe(binfo);
    }

}

結果:

print

很明顯,我們需要編寫一種轉換機制,將表示16進位制的資料對應成為鍵盤按鍵。

鍵盤上需要顯示的有字母和特殊符號,還有一些功能性的按鍵shift,backspace等。

測試記錄了幾個按鍵的按下資料

鍵盤 按下

F1 3B

F2 3C

F3 3D

F4 3E

A 1E

B 30

Backspace OE

空格 39

既然已經知道了對應關係,那麼很容易就可以建立一種對應。

先來實現這幾個特殊按鍵功能

我打算將 F1 實現為 clear 功能,實現頁面重新整理 。 Backspace 實現回退功能。Enter實現確定以及回車功能。

void showkey(struct BOOTINFO *binfo,char s[40]){
    // 回車鍵 
    if(strcmp(s,"1C")==0){ 
            write_x = 55 ;  // 游標移動至下一行起始位置。
            write_y += 19 ;
            showkeys(binfo->vram, binfo->scrnx, 0, write_y, COL8_FFFFFF, "AntzOS>");
    }
    // F1   重新整理本頁
    else if(strcmp(s,"3B")==0){
            new_pe(binfo);
    }
    // 空格  游標後移一位
    else if(strcmp(s,"39")==0){
            showkeys(binfo->vram, binfo->scrnx,  write_x,  write_y, COL8_FFFFFF, " ");
            write_x += 19 ;
    }
    // Backspace 刪除退格
    else if(strcmp(s,"0E")==0){
            // 回退
            write_x -= 19 ;
            //重新覆蓋這片區域
            area_flash(binfo->vram, binfo->scrnx , COL8_000000,  write_x,     write_y,     write_x+19, write_y+19);
    }
    // 其他按鍵
    else {
            showkeys(binfo->vram, binfo->scrnx,  write_x,  write_y, COL8_FFFFFF, s);
            write_x += 19 ;
    }
    if(write_x>155){
        write_x = 55 ;
        write_y += 19 ;
        //putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>");
    }
    if(write_y>180){
        new_pe(binfo);
    }

}

字母識別同理,當然可以比上面實現的更加完善更加簡潔,但我倉促之下就只能先做到這一步。

三 . Bug引發的思考

這裡開始就和AntzOs實現沒有多少聯絡了,不過在我測試按鍵中斷時候發現了很多奇怪的小問題。

Caps Lock(大小寫鍵) 是否開啟並不會影響中斷對你一個按鍵的返回資訊,也就是所謂的大小寫中斷其實是無法區分的,那麼現代系統如何區分呢? 同理於上面我們區分按下和彈起兩次中斷,我們可以將Caps Lock鍵的狀態獲取到,從而對當前按鍵進行所謂的大小寫區分。

按下兩次導致規則置換,會不會是因為中斷響應的時間導致的。