8086鍵盤輸入實驗——《x86組合語言:從真實模式到保護模式》讀書筆記07
1.BIOS中斷
我們可以為所有中斷型別自定義中斷處理過程,包括內部中斷、硬體中斷和軟中斷。
BIOS中斷,又稱BIOS功能呼叫,主要是為了方便地使用最基本的硬體訪問功能。通常,為了區分針對同一硬體的不同功能,使用暫存器AH來指定具體的功能編號。
比如說,以下的指令用於從鍵盤讀取一個按鍵:
mov ah,0x00 ;0功能號對應從鍵盤讀字元 int 0x16 ;鍵盤服務, int 0x16 ; 中斷返回時,字元的ASCII在AL中
需要說明的是,BIOS可能會為一些簡單地外圍裝置提供初始化程式碼和功能呼叫程式碼,並填寫中斷向量表,但是有一些BIOS中斷是由外部裝置介面自己建立的。
首先,每個外部裝置介面,包括各種板卡,如網絡卡、顯示卡、鍵盤介面電路、硬體控制器等,都有自己的只讀儲存器(ROM),類似於BIOS晶片,這些ROM中提供了它們自己的功能呼叫例程,以及本裝置的初始化程式碼。按照規範,前兩個單元的內容是0x55和0xAA,第三個單元是本ROM中的程式碼長度(以512位元組為單位);從第四個單元開始,就是實際的ROM程式碼。
其次,我們知道,從記憶體實體地址A0000開始,到FFFFF結束,有相當一部分空間是留給外圍裝置的。如果裝置存在,那麼它自帶的ROM會對映到分配給它的地址範圍內。
在計算機啟動期間,BIOS會以2KB為單位搜尋記憶體地址C0000~E0000之間的區域。當它發現某個區域的前兩個位元組是0x55和0xAA時,那意味著該區域有ROM程式碼的存在,是有效的。接著,它對該區域做累加和檢查,看結果是否和第三個單元相符。如果相符,就從第四個單元進入。這時候,處理器執行的是硬體自帶的程式指令,這些指令初始化外部裝置的相關暫存器和工作狀態。最後,填寫相關的中斷向量表,使其指向自帶的中斷處理過程。
2.鍵盤讀字元並顯示的實驗
(1)程式碼清單
;程式碼清單9-2 ;檔名:c09_2.asm ;檔案說明:用於演示BIOS中斷的使用者程式 ;建立日期:2012-3-28 20:35 ;=============================================================================== SECTION header vstart=0 ;定義使用者程式頭部段 program_length dd program_end ;程式總長度[0x00] ;使用者程式入口點 code_entry dw start ;偏移地址[0x04] dd section.code.start ;段地址[0x06] realloc_tbl_len dw (header_end-realloc_begin)/4 ;段重定位表項個數[0x0a] realloc_begin: ;段重定位表 code_segment dd section.code.start ;[0x0c] data_segment dd section.data.start ;[0x14] stack_segment dd section.stack.start ;[0x1c] header_end: ;=============================================================================== SECTION code align=16 vstart=0 ;定義程式碼段(16位元組對齊) start: mov ax,[stack_segment] mov ss,ax mov sp,ss_pointer mov ax,[data_segment] mov ds,ax mov cx,msg_end-message mov bx,message .putc: mov ah,0x0e mov al,[bx] int 0x10 inc bx loop .putc .reps: mov ah,0x00 int 0x16 mov ah,0x0e mov bl,0x07 int 0x10 jmp .reps ;=============================================================================== SECTION data align=16 vstart=0 message db 'Hello, friend!',0x0d,0x0a db 'This simple procedure used to demonstrate ' db 'the BIOS interrupt.',0x0d,0x0a db 'Please press the keys on the keyboard ->' msg_end: ;=============================================================================== SECTION stack align=16 vstart=0 resb 256 ss_pointer: ;=============================================================================== SECTION program_trail program_end:
(2)使用BIOS中斷向螢幕寫字元
關於程式碼,頭部的部分和SS,DS的初始化自然不用多說,我們已經很熟悉了。
mov cx,msg_end-message mov bx,message .putc: mov ah,0x0e mov al,[bx] int 0x10 inc bx loop .putc
首先,把重複次數傳入CX,然後讓BX指向要顯示的資訊的首地址。
接下來,我們要利用0x10號中斷的0x0e號功能。
BIOS中斷顯示服務(Video Service——INT 10H)
功能描述:在Teletype模式下顯示字元,具體說就是在螢幕的游標處寫一個字元,並推進游標的位置。
入口引數:
AH=0EH
AL=字元
BH=頁碼
BL=前景色(圖形模式);注意,僅在圖形模式下,設定BL才會改變前景色;在文字模式下,這個引數不起作用(我們的實驗工作在文字模式下)
出口引數:無
(3)使用BIOS中斷從鍵盤讀取字元
.reps: mov ah,0x00 int 0x16 mov ah,0x0e mov bl,0x07 ;我覺得這句可以不要 int 0x10 jmp .reps
前面已經說了,0x16號中斷的0x00號子功能是從鍵盤讀字元。
然後,再次利用0x10號中斷的0x0e號功能,把我們從鍵盤輸入的字元顯示出來。
BIOS中斷鍵盤服務(Keyboard Service——INT 16H)
功能描述:從鍵盤讀入字元
入口引數:
AH=00H——讀鍵盤
AH=10H——讀擴充套件鍵盤(可根據0000:0496H單元的內容判斷:擴充套件鍵盤是否有效 )
出口引數:
AH=鍵盤的掃描碼
AL=字元的ASCII碼
(4)實驗結果截圖
上圖就是啟動Bochs後,再按C之後的畫面。接下來,我們就可以嘗試按鍵,看看會發生什麼
下一次,我們就開始探索32位的x86了,你是否很期待呢?