彙編17 使用BIOS進行鍵盤輸入和磁碟讀寫

2022-08-19 14:54:18 字數 3788 閱讀 2013

我們通過討論鍵盤輸入和磁碟讀寫來理解cpu對i/o的控制。

鍵盤輸入會引發9號中斷,cpu會執行中斷例程,從60h埠讀出掃瞄碼,然後將其轉換為對應的ascii碼資訊,將掃瞄碼和對應的ascii碼存入記憶體中的指定空間中,這個空間一般是鍵盤緩衝區,鍵盤緩衝區是乙個環形佇列。

如果我們按下a鍵就會引發鍵盤中斷,cpu執行int9中斷例程,從60h埠讀出a鍵的通碼,然後檢測狀態位元組,將a的掃瞄碼1eh和對應的ascii碼61h寫入鍵盤緩衝區中:

接下來按下b、c、d、e後,緩衝區的內容如下,每個字單元的高位位元組儲存掃瞄碼,低位位元組儲存ascii碼:

然後我們按下左shift鍵,此時int9接受到左shift的通碼,設定0040:17處的狀態位元組的第一位為1,緩衝區不變。

此時按下a鍵,因為檢測到狀態位元組的改變,所以能確認左shift被按下,所以此時對應的ascii碼為大寫字母的ascii碼41h,緩衝區內容如下:

鬆開左shift鍵也會引發中斷例程,然後將對應狀態位元組恢復為0.

bios提供了int16h中斷例程供程式設計師使用,它有乙個功能是從鍵盤緩衝區中讀取乙個鍵盤輸入,該功能的編號為0,下列指令可以讀取乙個鍵盤輸入,同時將其從緩衝區中刪除:

mov ah,0

int 16h

執行完畢後,ah中是掃瞄碼,al中是ascii碼。

這段**執行後會檢查鍵盤緩衝區中是否有資料,如果沒有就一直檢測,如果有的話再執行讀取和從緩衝區中刪除。可見,int9中斷例程和int16h中斷例程是一對相互配合的程式。

最基本的字串輸入程式,需要具備下面的功能:

1、在輸入的同時需要顯示這個字串

2、一般在輸入回車符後,字串輸入結束

3、能夠刪除已經輸入的字元

我們輸入字元的時候是從左往右,但是刪除時是先刪除最右邊的字元,這說明字串應該用棧的形式儲存,每次輸入和刪除乙個字元的時候,應該將棧中的字串顯示到螢幕上,按下回車後可以在字串中加入0,代表字串結束。

程式的處理過程如下:

1、呼叫int16h讀取鍵盤輸入

2、如果是字元,進入字元棧,顯示字元棧中所有的字元,然後繼續執行1

3、如果是退格鍵,從字元棧中彈出乙個字元,顯示字元棧中所有的字元,繼續執行1

4、如果是enter就向字元棧中壓入0,然後返回

我們先把字元棧的入棧、出棧和顯示棧中的內容寫成子程式,引數說明:

ah是功能號,0表示入棧,1表示出棧,2表示顯示。ds:si指向字元棧空間,對0號功能,al是入棧字元;對1號功能,al是返回的字元;對於2號功能,dh和dl代表螢幕上顯示的行、列位置。

程式如下:

charstack:	jmp short charstart

table dw charpush,charpop,charshow 建立定址表

top dw 0

charstart: push bx

push dx

push di

push es

cmp ah,2

ja sret 如果ah大於2跳轉到sret結束子程式

mov bl,ah

mov bh,0

add bx,bx 組成bx然後增加一倍

jmp word ptr table[bx] 呼叫對應的程式

charpush: mov bx,top

mov [si][bx],al

inc top 入棧後修改指標的值

jmp sret

charpop: cmp top,0

je sret 如果棧為空則直接跳轉到sret

dec top

mov bx,top

mov al,[si][bx] 出棧後修改指標的值

jmp sret

charshow: mov bx,0b800h

mov es,bx

mov al,160

mov ah,0

mul dh

mov di,ax

add dl,dl

mov dh,0

add di,dx

mov bx,0 初始化bx為0

charshows: cmp bx,top 比較bx和top的值判斷棧是否為空

jne noempty

mov byte ptr es:[di],' ' 為空則顯示空格

jmp sret

noempty: mov al,[si][bx]

mov es:[di],al

mov byte ptr es:[di+2],' '

inc bx 不為空顯示對應單元的值然後更新指標

add di,2

jmp charshows

sret: pop es

pop di

pop dx

pop bx

ret

完整程式如下:

getstr:	push ax

getstrs:mov ah,0

int 16h 讀取鍵盤緩衝區

cmp al,20h

jb nochar ascii碼低於20h說明不是字元轉到nochar

mov ah,0

call charstack 如果是字元就將其入棧

mov ah,2

call charstack 顯示字串

jmp getstrs

nochar: cmp ah,0eh

je backspace 如果掃瞄碼為0eh就轉到backspace

cmp ah,1ch

je enter 如果掃瞄碼為1ch就轉到enter

jmp getstrs 否則繼續呼叫本程式

backspace: mov ah,1

call charstack

mov ah,2

call charstack 先出棧再顯示字串

jmp getstrs

enter: mov al,0

mov ah,0

call charstack 將0入棧,表示字串的輸入結束

mov ah,2

call charstack 顯示字串

pop ax

ret

bios提供的訪問磁碟的中斷例程為int 13h,讀取0面0道1扇區的內容到0:200的程式如下:

mov ax,0

mov es,ax

mov bx,200h es:bx指向接受資料的記憶體區

mov al,1 讀取的扇區數

mov ch,0 磁軌號為0

mov cl,1 扇區號為1

mov dl,0

mov dh,0 磁頭號,也就是面號為0

mov ah,2 2功能代表讀扇區

int 13h

dl是驅動器號,對於軟碟機來講0是軟碟機a,1是軟碟機b,對於硬驅來講,80h是硬碟c,81h是硬碟d。

如果讀取成功,則ah為0,al為讀入的扇區數,如果讀取失敗,ah裡面是出錯**。

如果是向磁碟寫入,只需要將ah代表的功能號改為3即可,就可以將0:200的內容寫入磁碟對應位置。

彙編第十七節 使用BIOS進行鍵盤輸入和磁碟讀寫

cpu在9號中斷發生後,執行int9中斷例程,從60h埠讀出掃瞄碼,並將其轉化為相應的ascii碼或狀態資訊,儲存在記憶體的指定空間 鍵盤緩衝區或狀態位元組 中 比如 a鍵的掃瞄碼1eh和對應的ascii碼,即字母 a 的ascii碼61h,寫入鍵盤緩衝區。緩衝區的字單元中,高位位元組儲存掃瞄碼,低...

用80x86組合語言程式設計 鍵盤輸入與顯示輸出

要求 從鍵盤輸入一行字元,要求第乙個鍵入的字元必須是空格,不是,就退出。如果是的話,開始接收字元並存放在首位址buffer的緩衝區內,直到接收到第二個空格時結束。然後輸出這個字串。懸賞分 15 下列程式,經過檢驗,符合條件要求。data segment buffer db 80 dup data e...

使用DFS進行拓撲排序,如果可以完成的話,輸出路徑

進行深度優先搜尋的時候,如果當前訪問的點是已經被訪問過的節點的話,說明出現了逆邊。因此有環,無法完成拓撲排序。如果可以完成拓撲排序,檢測點序列就是乙個合法的拓撲排序 include include using namespace std class solution cout endl bool d...