第17章 使用BIOS进行键盘输入和磁盘读写

引言

大多数有用的程序都需要处理用户的输入,键盘输入是最基本的输入

程序和数据通常需要长期存储,磁盘是最常用的存储设备

BIOS为这两种外设的I/O提供了最基本的中断例程,

我们已经讲过,键盘输入将引发9号中断,BIOS提供了int 9中断例程。

cpu在9号中断发生后,执行 int 9中断例程,从60h端口中读出扫描码,并将其转化为相应的ASCII码或状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中。

一般的键盘输入,在cpu执行完int  9中断例程后,都放到了键盘缓冲区中。

键盘缓冲区中有16个字单元,可以存储15个按键的扫描码和对应的ASCII码

 

17.2  使用int  16h中断例程读取键盘缓冲区

BIOS提供了int 16h中断例程供程序员调用。

int  16h中断例程中包含的一个最重要的功能是从键盘缓冲区中读取一个键盘输入,该功能的编号为0

下面的指令从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除:

mov  ah,0

int  16h

结果:

ah=扫描码

al=ASCII码

int  16h中断例程的0号功能,进行如下的工作:

1)检测键盘缓冲区中是否有数据

2)没有则继续做第1步。

3)读取缓冲区第一个字单元中的键盘输入。

4)将读取的扫描码送入ah,ASCII码送入al

5)将已读取的键盘输入从缓冲区删除。

可见,BIOS的int 9中断例程和int  16h中断例程是一对相互配合的程序,int 9中断例程向键盘缓冲区中写入,int 16h中断例程从缓冲区中读出。

他们写入和读出的时机不同,int 9中断例程在有键按下的时候向键盘缓冲区中写入数据

而int  16h中断例程是在应用程序对其进行调用的时候,将数据从键盘缓冲区中读出。

我们在编写一般的处理键盘输入的程序的时候,可以调用int  16h从键盘缓冲区中读取键盘的输入。

第17章   使用BIOS进行键盘输入和磁盘读写

 

 

;编程:
;接收用户的键盘输入,输入“r”,将屏幕上的字符设置为红色:输入“g”, 
;将屏幕上的字符设置为绿色;输入“b ”,将屏幕上的字符设置为蓝色。


;A、B、C处的程序指令比较有技巧,请读者自行分析

assume cs:code

code segment
start:    mov ah,0
    int 16h
        
    mov ah,1            ;A
    cmp al,r
    je red
    cmp al,g
    je green
    cmp al,b
    je blue
    jmp short sret
    
red:    shl ah,1            ;B
green:    shl ah,1            ;C

blue:    mov bx,0b800h
    mov es,bx
    mov bx,1
    mov cx,2000
s:    and byte ptr es:[bx],11111000b
    or es:[bx],ah
    add bx,2
    loop s

sret:    mov ax,4c00h
    int 21h
code ends
end start

 

17.3  字符串的输入

用户通过键盘输入的通常不仅仅是单个字符而是字符串

下面我们讨论字符串输入中的问题和简单的解决方法。

最基本的字符串输入程序,需要具备下面的功能:

1)在输入的同时需要显示这个字符串

2)一般在输入回车符后,字符串输入结束。

3)能够删除已经输入的字符。

第17章   使用BIOS进行键盘输入和磁盘读写

 

 

;最基本的字符串输入程序,需要具备下面的功能:
;(1) 在输入的同时需要显示这个字符串;
;(2)一般在输入回车符后,字符串输入结束;
;(3)能够删除已经输入的字符。

;编写一个接收字符串的输入子程序,实现上面三个基本功能。
;因为在输入的过程中需要显示,子程序的参数如下:
;    (dh)、(dl)=字符串在屏幕上显示的行、列位置;
;    ds:si 指向字符串的存储空间,字符串以O 为结尾符。


assume cs:code

code segment
start:    
    call getstr    

return:    mov ax,4c00h
    int 21h


;完整的接收字符串输入的子程序

getstr:    push ax 

getstrs:mov ah,0
    int 16h
    
    cmp al,20h
    jb nochar   ;判断的是ASCII码小于0,说明不是字符
    mov ah,0;
    call charstack;字符入栈
    mov ah,2
    call charstack;显示栈中的字符
    jmp getstrs


nochar:    cmp ah,0eh;退格键的扫描码
    je backspace
    cmp ah,1ch;回车键的扫描码
    je 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 ;getstr ends


;功能子程序实现

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
    mov bl,ah
    mov bh,0
    add 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
    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

charshows:cmp 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



code ends
end start

 

第17章 使用BIOS进行键盘输入和磁盘读写

上一篇:Chrome 调试IOS真机页面


下一篇:spring+mybatis使用MapperScannerConfigurer简化配置