转载:http://www.cnblogs.com/dennisOne
☞使用BIOS进行键盘输入和读取键盘缓冲区
-
复习键盘缓冲区和状态字节
(1). BIOS键盘缓冲区是系统启动后,BIOS用于存放int 9中断例程所接受的键盘输入的内存区。键盘缓冲区有16个字单元,可以存储15个按键的扫描码和对应的ASCII码,高位字节是扫描码,低位字节是字符码。
(2). 状态字节存放在0040:17单元。该字节记录了控制键和切换键的状态。 -
int 9中断例程
键盘输入将引发9号中断,BIOS提供了int 9中断例程。CPU在9号中断发生后,执行9号中断例程,从60号端口读出扫描码,将其转化为相应的ASCII码或者状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中。
eg:简述Shift_A
(1). 按下左Shift键,引发键盘中断;int 9中断例程接受左Shift键的通码,设置0040:17处的状态字节的第1位为1,表示左Shift键按下。
(2). 按下A键,引发键盘中断;CPU执行int 9中断例程,从60h端口读出A键的通码;检测状态字节,看看是否有切换键按下,发现左Shift键被按下,则将A键的扫描码1Eh和Shift_A对应的ASCII码,即大"A"的ASCII码41h,写入键盘缓冲区。
(3). 松开左Shift键,引发键盘中断;int 9中断例程接受左Shift键的断码,设置0040:17处的状态字节的第1位为0,表示左Shift键松开。 -
使用int 16h中断例程读取键盘缓冲区
mov ah, 0
int 16h
结果: (ah)=扫描码,(al)=ASCII码。
int 16h中断例程检测键盘缓冲区,发现缓冲区空,则循环等待,直到缓冲区中有数据。 -
int 9 中断例程和int 16h 中断例程 是一对相互配合的程序。int 9 中断例程向键盘缓冲区中写入,int 16 例程 从缓冲区读出。
☞模拟dos的字符串输入程序
tips:
(1)在数据读入的时候,采用队列的形式。先进,先读取。
(2)在数据操作(删除)的时候,采用栈的形式。后进,先删。
代码
下面的程序写的非常漂亮。
(1)用ds指向段地址,si指向栈底,top指向栈顶。此时si有点像数组的首地址。回想一下,ss:sp,由于没有栈底,只有栈顶,无法判断是否越界。
(2) 这次程序中使用的是 jmp word ptr table[bx] 。上一张的大程序,用的是call。这也是处理标号常量的一种思路,当然在这次的代码中没有涉及到而已。它让所有的程序都从结尾处返回。调用函数的时候,用call和jmp都有他们的好处。但是我个人爱好call。比较统一。
assume cs:code, ds:data
data segment
dw 100 dup (0) ; 模拟读取字符的栈
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, 0
; 将ds:si设置为存放字符的栈
call getstr
return:
mov ax, 4c00h
int 21h
; 完整的接受字符串输入的子程序
getstr:
push ax
getstrs:
mov ah, 0
int 16h
cmp al, 20h
jb nochar ; ASCII码小于20h, 说明不是字符
; 字符的处理分为两步,1:入栈,2:显示栈中的字符
mov ah, 0 ; 1: 字符入栈
call charstack
mov ah, 2 ; 2: 显示栈中的字符
call charstack
jmp getstrs
nochar:
cmp ah, 0eh ; 退格键的扫描码
je backspace
cmp ah, 1ch ; Enter键的扫描码
je enters
jmp getstrs ; 其他控制键忽略
backspace:
mov ah, 1
call charstack ; 字符出栈
mov ah, 2
call charstack ; 字符显示
jmp getstrs
enters:
mov al, 0
mov ah, 0
call charstack ; 0入栈
mov ah, 2
call charstack ; 显示栈中的字符串
pop ax
ret
; 子程序: 字符栈的入栈、出栈和显示
; 参数说明:(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
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: ;(dh)、(dl)=字符串在屏幕上显示的行、列位置。
cmp 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 ; 设置 es:di
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
☞对磁盘进行读写实验:略