汇编语言笔记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

转载于:https://www.cnblogs.com/dennisOne/archive/2012/10/28/2743505.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值