自制作業系統Antz day10——實現shell(上)
阿新 • • 發佈:2018-12-14
我已經規範了系統程式碼風格,類似於按照linux分包,把各部分功能區分開了
在之前的任務中,我們已經通過直接操作顯示卡驅動完成了簡單的圖形化。
需要了解之前的部分:
直接操作顯示卡請參考day03
簡單圖形化的實現請參考day09
Makefile
專案目錄
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); } }
結果:
很明顯,我們需要編寫一種轉換機制,將表示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鍵的狀態獲取到,從而對當前按鍵進行所謂的大小寫區分。
按下兩次導致規則置換,會不會是因為中斷響應的時間導致的。