在上一篇,我講了鍵盤操做會產生掃描碼以及如何解析Pause
鍵和Print Screen
鍵的掃描碼。linux
在這一篇,我會說清楚」鍵盤上的輸入爲何會出如今顯示器上「。數組
在上一篇,我創建了一個Make Code和按鍵ASCII碼(部分按鍵如Enter是我本身設置的值)的映射數組keyboardMap
。spa
按鍵不是Pause
,也不是Print Screen
,就進入下面的解析流程。操作系統
V
,keyboardMap[V *3]
。V
。keyboardMap
中查詢出被按下的鍵是left_shift
或right_shift
。column
的值是1。N
。keyboardMap[N * 3 + column]
。注意,查詢到的鍵值是keyboardMap[N * 3 + column]
。這就是鍵盤上的1
、A
這類按鍵與shift
鍵組合時的值,即默認值外的另外一個值。命令行
請想想,點擊shift + A
鍵,讀取掃描碼的過程是什麼樣的?設計
Enter鍵和Backspace鍵很容易解析。獲取掃描碼(Make Code)S,獲取鍵值keyboardMap[N * 3]
。rest
根據鍵值識別出是Enter鍵後就把光標設置到下一行。code
識別出是Backspace就這樣處理最新的兩個字節:將高字節設置成0Fh
,將低字節設置成空字符的ASCII碼;另外,將光標的位置後退兩個字符。blog
沒有弄明白。索引
使用linux的命令行、顯示器上打印滿了字符,咱們能夠使用clear
讓命令行終端的字符所有消失。讓屏幕上的字符所有消失,這就是清屏。
clear
命令只是移動了光標的位置,並無清除屏幕上的字符。按下方向鍵中的Up
能定位到已經消失的字符。
咱們的清屏,是讓字符完全從屏幕上消失,不管怎麼按Up
鍵都不會再看到字符。
清屏其實很簡單,就是往寫滿字符的顯存區域寫入空字符。
我以爲tty
是一個比較過期的功能,我幾乎沒用過。
想體驗一番tty
是什麼的同窗,能夠在安裝了linux系統的電腦或虛擬機上按下shift + alt + f1
或shift + alt + f2
鍵在不一樣的tty之間切換。下面是我在虛擬機上切換tty的效果,一個是圖形界面,一個是純命令行界面。
我只講述VGA
模式下的tty。
如上圖所示,不一樣的tty窗口展現的內容徹底不相同,在tty0窗口敲擊鍵盤,數據只會出如今tty0的顯示器;切換到tty1後,顯示器上不會出現剛剛敲擊鍵盤的數據;反過來也是同樣。
不一樣tty之間,是徹底隔離的,只是公用一個鍵盤。
VGA
是什麼呢?我以爲弄清楚這個概念的方方面面沒有更多的做用。對VGA
,瞭解有限的下面這些有限的知識就夠了。
在這種模式下,顯示器一共能顯示25行字符,每行80個字符。
每一個字符佔用2個字節,高字節是字符的顏色,低字節是字符的ASCII碼。例如
mov ah, 0Ah mov al, 'A'
mov ah, 0Ah
中的 0Ah
的高4位和低4位分別是: 0000b
和 1010b
。它們分別設置字符的背景色和前景色。
mov al, 'A'
中的 A
是要打印的字符。
VGA
模式下的顯示器是一個硬件,提供了多組寄存器。
讀寫這些寄存器,能設置光標的位置、點擊Up
等方向鍵能滾屏。
讀寫這類寄存器,需先往一類寄存器中寫入另外一類寄存器的索引,即往另外一類寄存器的第N個寄存器中寫入數據;而後往第二類寄存器寫入數據,不須要再指定具體是哪一個寄存器。
顯示器上的內容是顯存中的數據的映射。要讓不一樣的tty窗口打印不一樣的內容,只需把顯存分割成若干塊,每一個tty分配一塊。
顯示器一滿屏所需空間是80 * 25 * 2 = 4000
個字節。顯存的內存地址是0xB8000~~~0xBFFFF
,總計0xBFFFF - 0xB8000 + 1 = 0x8000 = 32768
字節。若是實現3個tty,每一個tty對應的顯存大小大概是32768 / 3 = 10922
個字節,能存儲兩」滿屏「數據。
每一個tty設計一個緩衝區C1,數據從鍵盤緩衝區C2到這個緩衝區,而後再從C1讀取數據寫入對應tty的顯存區域。
tty對應的顯存區域,也設計一個結構來存儲,叫Console
。
直接看僞代碼吧。
typedef struct{ // tty使用的顯存的開始位置 int original_address; // tty使用的顯存的大小 int limit; // tty使用顯存的當前位置 int current_address; // tty的光標位置 int cursor_address; }Console; typedef struct{ // 緩衝區下一個要處理的字符的 int tail; // 緩衝區下一個空閒位置 int head; // 緩衝區存儲的數據的數量 int count; // 存儲數據的數組 int buff[256]; Console * console; }TTY;
restart
運行tty任務。save
當前進程,從C2讀取數據,而後放入C1。