王爽 《汇编语言》 读书笔记 十七
2017-09-24 11:06
295 查看
第十七章 使用BIOS进行键盘输入和磁盘读写
17.1 int9中断例程对键盘输入的处理
一般的键盘输入,在cpu执行完int9中断例程以后,欧放到了键盘缓冲区中。 键盘缓冲区有16个字单元,可以存储15个按键的扫描码和对应的ASCII码。
参照书P300页 关于键盘缓冲区的存储利用了队列或者环形队列数据结构。
17.2 使用int16h中断例程读取键盘缓冲区
int16h 能够从键盘缓冲区读取一个键盘输入, 功能标号为0.
mov ah, 0
int 16h
结果 ah = 扫描码 bl = ascii码
然后该字符从键盘缓冲区被删除
int 16h中断例程检测键盘缓冲区,发现缓冲区为空,则循环等待,直到缓冲区中有数据。
int 16h的中断例程0号功能,进行如下工作
1)检测键盘缓冲区是否有数据
2)没有则继续第一步
3)读取缓冲区第一个字单元的键盘输入
4)将读取的扫描码送入ah, ASCII码送入al
5)将已读取的键盘输入从缓冲区中删除。
编程,接受用户的键盘输入,输入“r” ,将屏幕上的字符设置为红色,输入“g”, 将屏幕上的字符设置为绿色
输入“b“ 将屏幕上的字符设置为蓝色。
监测点17.1
"在int 16h中断例程中,一定有设置IF=1的指令." 这种说法对吗?
不对.
8086CPU的中断系统具有256个中断(0-255),其中分为
(1)外部中断:又分为 1. 可屏蔽中断,可以由标志寄存器中的IF位控制是否屏蔽(IF=0则屏蔽);
2. 不可屏蔽中断, 中断向量号为02;
(2)内部中断: 包括除法溢出中断,int指令中断,溢出中断,单步中断, 不受标志寄存器的IF位控制;
题意中设置为1是为了保证在读取键盘缓冲区的第一个字节内容时,键盘中断可以响应, 以便将相应按键加入键盘缓冲区中,
但是按下键即调用 int 9h, 属于内部中断, 不受IF位的控制, 故不需要将IF设置为1。
故这种说法错误。
17.3 字符串的输入
基本的字符串输入程序,需要具备下面的功能。
1)在输入的同时需要显示这个字符串:
2)一般在输入回车符后,字符串输入结束;
3)能够删除已经输入的字符。
17.4 应用int 13h中断例程对磁盘进行读写
需要先在虚拟机中创建虚拟软盘
参考这篇blog: http://blog.csdn.net/apollon_krj/article/details/72026944
3.5 英寸软盘分为上下两面,每个面80个磁道,每个磁道有18个扇区,每个扇区512个字节。
只能以扇区为单位对磁盘进行读写。
bios采用int 13h来访问磁盘。
读取0 面 0 道 1扇区道内容道0:200点程序如下
入口参数
ah = 13h 的功能号(2表示读扇区)
al = 读取扇区数
ch = 磁道号
cl = 扇区号
dh = 磁头号(也就是软盘的面号)
dl=驱动器号(软驱从0开始代码 A, 1 代表B)
es:bx指向接受从扇区读入数据的内存区。
返回参数:
操作成功: ah = 0, al = 读入扇区的数量
操作失败: ah = 错误代码
将0:200点内容写入0面0道1扇区
入口参数:
ah = int13h 功能号(3表示写扇区)
al = 写入扇区数
ch = 磁道号
cl = 扇区号
dh = 磁头号
dl = 驱动器号
es:bx指向写入磁盘的数据
将当前屏幕的内容保存在磁盘上。
注意写入软盘的0扇区会破坏文件系统导致软盘在当前操作系统下不可用。
写入以后发现windows会提示磁盘未格式化。(文件系统被破坏了)
实验17 编写包含多个功能子程序的中断例程。
安装一个新的int 7ch中断例程,实现通过逻辑扇区号对软盘进行读写。
参数说明
1)用ah 寄存器传递功能号: 0表示读,1表示写
2)用dx寄存器传递要读写的扇区的逻辑扇区号;
3)用es:bx指向存储读初数据或写入数据的内存区。
提示,用逻辑扇区号计算出面号,磁道号,扇区号后,调用int 13h 中断例程进行实际的读写。
安装int7ch的磁盘读写例程
例如可以将当前屏幕内容写入磁盘。然后再读取出来。
实现在软盘中写入了512x8的屏幕内容
接着读取
载入了之前写入磁盘的内容。说明IO功能有效。
17.1 int9中断例程对键盘输入的处理
一般的键盘输入,在cpu执行完int9中断例程以后,欧放到了键盘缓冲区中。 键盘缓冲区有16个字单元,可以存储15个按键的扫描码和对应的ASCII码。
参照书P300页 关于键盘缓冲区的存储利用了队列或者环形队列数据结构。
17.2 使用int16h中断例程读取键盘缓冲区
int16h 能够从键盘缓冲区读取一个键盘输入, 功能标号为0.
mov ah, 0
int 16h
结果 ah = 扫描码 bl = ascii码
然后该字符从键盘缓冲区被删除
int 16h中断例程检测键盘缓冲区,发现缓冲区为空,则循环等待,直到缓冲区中有数据。
int 16h的中断例程0号功能,进行如下工作
1)检测键盘缓冲区是否有数据
2)没有则继续第一步
3)读取缓冲区第一个字单元的键盘输入
4)将读取的扫描码送入ah, ASCII码送入al
5)将已读取的键盘输入从缓冲区中删除。
编程,接受用户的键盘输入,输入“r” ,将屏幕上的字符设置为红色,输入“g”, 将屏幕上的字符设置为绿色
输入“b“ 将屏幕上的字符设置为蓝色。
assume cs:code code segment start: mov ah, 0 int 16h mov ah, 1 ; used to generate the color code cmp al, 'r' je red cmp al, 'g' je green cmp al, 'b' je blue jmp short sret red: shl ah, 1 ; left shift once green: shl ah, 1 ; left shift once . if go through red it will generate 100B blue: mov bx, 0b800h mov es, bx mov bx, 1 mov cx, 2000 s: and byte ptr es:[bx], 11111000b ; reset color or es:[bx], ah ; set new color add bx, 2 loop s sret: mov ax, 4c00h int 21h code ends end start
监测点17.1
"在int 16h中断例程中,一定有设置IF=1的指令." 这种说法对吗?
不对.
8086CPU的中断系统具有256个中断(0-255),其中分为
(1)外部中断:又分为 1. 可屏蔽中断,可以由标志寄存器中的IF位控制是否屏蔽(IF=0则屏蔽);
2. 不可屏蔽中断, 中断向量号为02;
(2)内部中断: 包括除法溢出中断,int指令中断,溢出中断,单步中断, 不受标志寄存器的IF位控制;
题意中设置为1是为了保证在读取键盘缓冲区的第一个字节内容时,键盘中断可以响应, 以便将相应按键加入键盘缓冲区中,
但是按下键即调用 int 9h, 属于内部中断, 不受IF位的控制, 故不需要将IF设置为1。
故这种说法错误。
17.3 字符串的输入
基本的字符串输入程序,需要具备下面的功能。
1)在输入的同时需要显示这个字符串:
2)一般在输入回车符后,字符串输入结束;
3)能够删除已经输入的字符。
assume cs:code data segment db 256 dup(' ') data ends stack segment db 64 dup(0) stack ends code segment start: mov ax, stack mov ss, ax mov sp, 64 mov ax, data mov ds, ax mov ax, 0 mov si, 0 mov dh, 5 mov dl, 0 call getstr mov ax, 4c00h int 21h ;getstr: getstr: push ax getstrs: mov ah, 0 int 16h cmp al, 20h jb nochar ; ascii code < 20h ,it is not a char mov ah, 0 call charstack ; push char mov ah, 2 call charstack ; charshow jmp getstrs nochar: cmp ah, 0eh ; backspace je backspace cmp ah, 1ch ; return key je return jmp getstrs backspace: mov ah, 1 call charstack ; pop char mov ah, 2 call charstack ; charshow jmp getstrs return: mov al, 0 mov ah, 0 call charstack ; push char '\0' mov ah, 2 call charstack ; showchar pop ax ret ; charstack ; push char into stack, pop up char from stack. and show the current char ; ah= 0 push, 1 pop 2 show ; ds:si point to the char stack. ; for 0 push al ; for 1 pop char and store to al ; for 2 dh, dl point to the position. Show the full string. charstack: jmp short charstart table dw charpush, charpop, charshow top dw 0 ; point to the top of the stack charstart: push bx push dx push di push es cmp ah, 2 ; invalid command ja charret mov bl, ah mov bh, 0 add bx, bx jmp word ptr table[bx] ; call the actual function. charpush: mov bx, top mov [si][bx], al inc top jmp charret charpop: cmp top, 0 je charret dec top mov bx, top mov al, [si][bx] jmp charret 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, ax ; calc the offset mov bx, 0 charshows: cmp bx, top jne noempty mov byte ptr es:[di], ' ' jmp charret noempty: mov al, [si][bx] mov es:[di], al ;and es:[di + 1], 11111000b ;or es:[di + 1], 10b ; set color mov byte ptr es:[di+2], ' ' inc bx add di, 2 jmp charshows charret: pop es pop di pop dx pop bx ret code ends end start
17.4 应用int 13h中断例程对磁盘进行读写
需要先在虚拟机中创建虚拟软盘
参考这篇blog: http://blog.csdn.net/apollon_krj/article/details/72026944
3.5 英寸软盘分为上下两面,每个面80个磁道,每个磁道有18个扇区,每个扇区512个字节。
只能以扇区为单位对磁盘进行读写。
bios采用int 13h来访问磁盘。
读取0 面 0 道 1扇区道内容道0:200点程序如下
mov ax, 0 mov es, ax mov bx, 200h mov al, 1 mov ch, 0 mov cl, 1 mov dl, 0 mov dh, 0 mov ah, 2 int 13h
入口参数
ah = 13h 的功能号(2表示读扇区)
al = 读取扇区数
ch = 磁道号
cl = 扇区号
dh = 磁头号(也就是软盘的面号)
dl=驱动器号(软驱从0开始代码 A, 1 代表B)
es:bx指向接受从扇区读入数据的内存区。
返回参数:
操作成功: ah = 0, al = 读入扇区的数量
操作失败: ah = 错误代码
将0:200点内容写入0面0道1扇区
mov ax, 0 mov es, ax mov bx, 200h mov al, 1 mov ch, 0 mov cl, 1 mov dl, 0 mov dh, 0 mov ah, 3 int 13h
入口参数:
ah = int13h 功能号(3表示写扇区)
al = 写入扇区数
ch = 磁道号
cl = 扇区号
dh = 磁头号
dl = 驱动器号
es:bx指向写入磁盘的数据
将当前屏幕的内容保存在磁盘上。
注意写入软盘的0扇区会破坏文件系统导致软盘在当前操作系统下不可用。
assume cs:code code segment start: mov ax, 0b800h mov es, ax mov bx, 0 mov al, 8 ; write 8sectors mov ch, 0 ; #of the track mov cl, 1 ; #of the first sector mov dl, 0 ; !!!!VERY IMPORTANT Drive A: mov dh, 0 ; #of disk face mov ah, 3 ; write floppy int 13h ; call int 13h mov ax, 4c00h int 21h code ends end start
写入以后发现windows会提示磁盘未格式化。(文件系统被破坏了)
实验17 编写包含多个功能子程序的中断例程。
安装一个新的int 7ch中断例程,实现通过逻辑扇区号对软盘进行读写。
参数说明
1)用ah 寄存器传递功能号: 0表示读,1表示写
2)用dx寄存器传递要读写的扇区的逻辑扇区号;
3)用es:bx指向存储读初数据或写入数据的内存区。
提示,用逻辑扇区号计算出面号,磁道号,扇区号后,调用int 13h 中断例程进行实际的读写。
安装int7ch的磁盘读写例程
assume cs:code stack segment db 64 dup(0) stack ends code segment start: ; set es:di as target address 0000:0200h mov ax, 0 mov es, ax mov di, 200h ; set ds:si as source address cs:sqr mov ax, cs mov ds, ax mov si, offset int7ch ; set cx as the data length mov cx, offset int7chend - offset int7ch ; set the transport directive DF = 0 cld cld rep movsb ; set the IRQ table 1F0 = 200h(IP) 1F2 = 0(CS) mov ax, 0 mov es, ax mov word ptr es:[7ch * 4], 200h ; install IRQ7ch mov word ptr es:[7ch * 4 + 2], 0 mov ax, 4c00h int 21h org 200h ;write/read floppy from logic sectors ;in ah 0 read, 1 write/read ,al number sectors to write ;dx store the logic sectors. ;es:bx point to the buffer int7ch: push cx push ax mov ax, dx call getsectors ; get pyhsical address of floppy cmp ah, 1 jne int7ret pop ax cmp ah, 0 je read cmp ah, 1 je write jmp int7ret ; return read: mov ah, 2 ; call #2 function of int13h int 13h jmp int7ret write: mov ah, 3 ; call #3 function of int13h int 13h int7ret: pop cx iret ; get the pyhsical face track and sector from logic #sectors ; in ax (store the logic #sectors from (0~1443)) ; out ; ah = 1 success, ah = 0 failed ; dh #of face ; dl drive: default = 0 ; ch #of track ; cl #of sector getsectors: push bx cmp ax, 2879 ja errors mov dx, 0 mov bx, 1440 div bx ; al = #face ah = 0 push dx ; store mode mov dh, al ; store face mov dl, 0 ; store drive label 0 pop ax mov bl, 18 div bl ; al = #track , ah = #sector - 1 mov ch, al ; store # track mov cl, ah inc cl ; store # sector mov ah, 1 jmp short retsectors ; return true errors: mov ah, 0 ; return false retsectors: pop bx ret int7chend: nop code ends end start执行代码:
assume cs:code code segment start: mov ax, 0b800h mov es, ax mov bx, 0 mov al, 8 ; write 8sectors mov ah, 0 ; read floppy of int7ch mov dx, 0 ; write logic sectors 1 int 7ch mov ax, 4c00h int 21h code ends end start
例如可以将当前屏幕内容写入磁盘。然后再读取出来。
实现在软盘中写入了512x8的屏幕内容
接着读取
载入了之前写入磁盘的内容。说明IO功能有效。
相关文章推荐
- 王爽 《汇编语言》 读书笔记 七 更灵活段定位内存地址段方法
- 王爽 《汇编语言》 读书笔记 十一 标志寄存器
- 《汇编语言》-王爽-第三版-读书笔记-前言
- 王爽 《汇编语言》 读书笔记 五 [BX]和loop指令
- 王爽 《汇编语言》 读书笔记 九 转移指令的原理
- 王爽 《汇编语言》 读书笔记 十四 端口
- 王爽 《汇编语言》 读书笔记 十五 外中断
- 《汇编语言-王爽》 读书笔记
- 王爽 《汇编语言》 读书笔记 三 寄存器(内存访问)
- 《汇编语言·王爽》读书笔记
- 王爽 《汇编语言》 读书笔记 十二 内中断
- 王爽 《汇编语言》 读书笔记 十 CALL和RET指令
- 王爽 《汇编语言》 读书笔记 四 第一个程序
- 王爽 《汇编语言》 读书笔记 六 包含多个段的程序
- 《汇编语言》(王爽)读书笔记
- 《汇编语言》(王爽著)的读书笔记(1)
- 王爽 《汇编语言》 读书笔记 一 基础知识
- 王爽 《汇编语言》 读书笔记 八 数据处理的两个基本问题
- 王爽 《汇编语言》 读书笔记 十三 int指令
- 《汇编语言》王爽 --实验十 显示字符串