您的位置:首页 > 移动开发 > IOS开发

汇编语言笔记17-使用BIOS进行键盘输入和磁盘读写

2016-08-23 09:12 1091 查看
转载必须注明出处,违者必究。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码或者状态信息,存储在内存的指定空间(键盘缓冲区状态字节)中。

示意图:



简述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相互暧昧,有这不同寻找的关系,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进行磁盘的读写

磁盘的读写原理

磁盘的实际访问由磁盘控制器进行,可以通过磁盘控制器访问磁盘。扇区是磁盘读写的最小单位。

磁盘寻址:
面号(从0开始)->磁道号(从0开始)->扇区号(从1开始)

BIOS提供int 13h中断例程来读写磁盘

读扇区
示例代码:
读取软盘的0面0道1扇区的内容到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


 

写扇区--入口参数和读扇区一致,只是功能号不一样

示例代码:将0:200的内容写入软盘的0面0道1扇区。

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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐