匯編語言筆記17-使用BIOS進行鍵盤輸入和磁盤讀寫


轉載必須注明出處,違者必究。http://www.cnblogs.com/dennisOne

使用BIOS進行鍵盤輸入和讀取鍵盤緩沖區

  1. 復習鍵盤緩沖區和狀態字節

    (1). BIOS鍵盤緩沖區是系統啟動后,BIOS用於存放int 9中斷例程所接受的鍵盤輸入的內存區。鍵盤緩沖區有16個字單元,可以存儲15個按鍵的掃描碼和對應的ASCII碼,高位字節是掃描碼,低位字節是字符碼。

    (2). 狀態字節存放在0040:17單元。該字節記錄了控制鍵和切換鍵的狀態。

  2. int 9中斷例程

    鍵盤輸入將引發9號中斷,BIOS提供了int 9中斷例程。CPU在9號中斷發生后,執行9號中斷例程,從60號端口讀出掃描碼,將其轉化為相應的ASCII碼或者狀態信息,存儲在內存的指定空間(鍵盤緩沖區狀態字節)中。

    示意圖:

    簡述Shift_A

    (1). 按下左Shift鍵,引發鍵盤中斷;int 9中斷例程接受左Shift鍵的通碼,設置0040:17處的狀態字節的第1位為1,表示左Shift鍵按下。

    (2). 按下A鍵,引發鍵盤中斷;CPU執行int 9中斷例程,從60h端口讀出A鍵的通碼;檢測狀態字節,看看是否有切換鍵按下,發現左Shift鍵被按下,則將A鍵的掃描碼1EhShift_A對應的ASCII碼,即大"A"的ASCII碼41h,寫入鍵盤緩沖區。

    (3). 松開左Shift鍵,引發鍵盤中斷;int 9中斷例程接受左Shift鍵的斷碼,設置0040:17處的狀態字節的第1位為0,表示左Shift鍵松開。

  3. 使用int 16h中斷例程讀取鍵盤緩沖區

    mov ah, 0

    int 16h

    結果: (ah)=掃描碼,(al)=ASCII碼。   

    int 16h中斷例程檢測鍵盤緩沖區,發現緩沖區空,則循環等待,直到緩沖區中有數據。

  4. int 9和int 16h相互曖昧,有這不同尋找的關系,xxoo~~~

   

模擬dos的字符串輸入程序

完整代碼:

  1     assume cs:code, ds:data
  2     
  3     data segment
  4         dw 100 dup (0)   ; 模擬讀取字符的棧
  5     data ends
  6     
  7     code segment
  8     start:
  9             mov ax, data
 10             mov ds, ax
 11             mov si, 0
 12             ; 將ds:si設置為存放字符的棧
 13             call getstr
 14     return:
 15             mov ax, 4c00h
 16             int 21h
 17             
 18     ; 完整的接受字符串輸入的子程序
 19     getstr:
 20             push ax
 21     
 22     getstrs:
 23             mov ah, 0
 24             int 16h
 25             cmp al, 20h
 26             jb nochar                        ; ASCII碼小於20h, 說明不是字符
 27             
 28             ; 字符的處理分為兩步,1:入棧,2:顯示棧中的字符
 29             mov ah, 0                        ; 1: 字符入棧
 30             call charstack
 31             mov ah, 2                        ; 2: 顯示棧中的字符
 32             call charstack
 33             jmp getstrs
 34                     
 35     nochar:    
 36             cmp ah, 0eh                    ; 退格鍵的掃描碼
 37             je backspace
 38             cmp ah, 1ch                    ; Enter鍵的掃描碼
 39             je enters
 40             jmp getstrs                    ; 其他控制鍵忽略
 41     
 42     backspace:
 43             mov ah, 1
 44             call charstack                    ; 字符出棧
 45             mov ah, 2
 46             call charstack                    ; 字符顯示
 47             jmp getstrs
 48     
 49     enters:
 50             mov al, 0
 51             mov ah, 0
 52             call charstack                    ; 0入棧
 53             mov ah, 2
 54             call charstack                    ; 顯示棧中的字符串
 55             
 56             pop ax
 57             ret
 58             
 59     
 60     ; 子程序: 字符棧的入棧、出棧和顯示
 61     ; 參數說明:(ah)=功能號,0表示入棧,1表示出棧,2表示顯示
 62     ; ds:si指向字符棧的空間
 63     ; 對於0號功能:(al)=入棧字符;
 64     ; 對於1號功能: (al)=返回的字符;
 65     ; 對於2號功能:(dh)、(dl)=字符串在屏幕上顯示的行、列位置。
 66     
 67     charstack:    jmp short charstart
 68         table     dw charpush, charpop, charshow
 69         top       dw 0                                ; 棧頂
 70         
 71     charstart:
 72                 push bx
 73                 push dx
 74                 push di
 75                 push es
 76     
 77                 cmp ah, 2
 78                 ja sret
 79                 mov bl, ah
 80                 mov bh, 0
 81                 add bx, bx
 82                 jmp word ptr table[bx]
 83                 
 84     charpush:    
 85                 mov bx, top
 86                 mov [si][bx], al
 87                 inc top
 88                 jmp sret
 89                 
 90     charpop:
 91                 cmp top, 0
 92                 je sret
 93                 dec top
 94                 mov bx, top
 95                 mov al, [si][bx]
 96                 jmp sret
 97                 
 98     charshow:   ;(dh)、(dl)=字符串在屏幕上顯示的行、列位置。
 99                 cmp bx, 0b800h
100                 mov es, bx
101                 mov al, 160
102                 mov ah, 0
103                 mul dh
104                 mov di, ax
105                 add dl, dl
106                 mov dh, 0
107                 add di, dx        ; 設置 es:di
108                 
109                 mov bx, 0
110     charshows:     cmp bx, top
111                 jne noempty
112                 mov byte ptr es:[di], ' '
113                 jmp sret
114     noempty:    
115                 mov al, [si][bx]
116                 mov es:[di], al
117                 mov byte ptr es:[di+2], ' '
118                 inc bx
119                 add di, 2
120                 jmp charshows
121     sret:        
122                 pop es
123                 pop di
124                 pop dx
125                 pop bx
126                 ret
127     
128     code ends
129 
130 end start

 

使用BIOS進行磁盤的讀寫

  1. 磁盤的讀寫原理

    磁盤的實際訪問由磁盤控制器進行,可以通過磁盤控制器訪問磁盤。扇區是磁盤讀寫的最小單位。

    磁盤尋址: 面號(0開始)->磁道號(0開始)->扇區號(1開始)

  2. BIOS提供int 13h中斷例程來讀寫磁盤
  3. 讀扇區

    示例代碼: 讀取軟盤的001扇區的內容到0:200

     1     assume cs:code
     2     
     3     code segment
     4     start:
     5             ; 入口參數設置
     6             mov ax, 0
     7             mov es, ax
     8             mov bx, 200         ; 1. es:bx 指向接受從扇區讀入數據的內存區
     9             
    10             mov al, 1            ; 2. (al)=需要讀取扇區的數
    11             
    12             mov dl, 0            ; 3. (dl)=驅動器號 軟驅從0開始, 0:軟驅A,1:軟驅B
    13                                  ;    硬盤從80h開始,80h:C盤,81h:D盤
    14             mov dh, 0            ; 4. (dh)=磁頭號(對於軟盤即面號,一個面對應一個磁頭)
    15             mov ch, 0            ; 5. (ch)=磁道號
    16             mov cl, 1            ; 6. (cl)=扇區號
    17             
    18             mov ah, 2            ; 7. (ah)=int 13h的功能號(2表示讀扇區)
    19             int 13h
    20             ; 返回參數:
    21             ; 操作成功: (ah)=0, (al)=讀入的扇區數
    22             ; 操作失敗: (ah)=出錯代碼
    23             
    24             mov ax, 4c00h
    25             int 21h
    26     code ends
    27     end start

     

  4. 寫扇區--入口參數和讀扇區一致,只是功能號不一樣

    示例代碼:將0:200的內容寫入軟盤的001扇區。

        assume cs:code
        
        code segment
        start:
                ; 入口參數設置
                mov ax, 0
                mov es, ax
                mov bx, 200          ; 1. es:bx 指向寫入磁盤的數據
                
                mov al, 1            ; 2. (al)=需要寫入扇區數
                
                mov dl, 0            ; 3. (dl)=驅動器號 軟驅從0開始, 0:軟驅A,1:軟驅B
                                     ;    硬盤從80h開始,80h:C盤,81h:D盤
                mov dh, 0            ; 4. (dh)=磁頭號(對於軟盤即面號,一個面對應一個磁頭)
                mov ch, 0            ; 5. (ch)=磁道號
                mov cl, 1            ; 6. (cl)=扇區號
                
                mov ah, 3            ; 7. (ah)=int 13h的功能號(3表示寫扇區)
                int 13h
                ; 返回參數:
                ; 操作成功: (ah)=0, (al)=寫入的扇區數
                ; 操作失敗: (ah)=出錯代碼
                
                mov ax, 4c00h
                int 21h
        code ends
    
    end start


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM