大多数有用的程序都需要处理用户的输入,键盘输入时最基本的输入。程序和数据通常需要长期存储,磁盘是最常用的存储设备。BOIS为这两种外设的I/O提供了最基本的中断例程,本章对它们的应用和相关问题进行讨论。
键盘输入将引发9号中断,BOIS提供了int9中断例程。CPU在9号中断发生后,执行int9中断例程,从60h端口读出扫描码,并将其转化为相应的ASCII码或者状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中。键盘缓冲区是用环形结构管理内存区,这里不过多深入,以几个键为例子看看int9中断例程对键盘输入的处理方法。
![780fff1da939be75b43a932ee56b3abf.png](https://i-blog.csdnimg.cn/blog_migrate/8c195d5783c596e83bcdbaf931fda4a3.jpeg)
![9e245a7ce757520442c56c0ce4109343.png](https://i-blog.csdnimg.cn/blog_migrate/56ee065185e04f65f1c5d0c5faeba02a.jpeg)
使用int16h中断例程读取键盘缓冲区。BOIS提供了int 16h中断例程供程序员调用。
int 16h中断例程包含一个最重要的功能是从键盘缓冲区读取一个键盘输入,该功能编号为0。下面的指令从缓冲区中读取一个键盘输入,并且将其从缓冲区删除:
![8050bba09584d34a34e4e815f056630f.png](https://i-blog.csdnimg.cn/blog_migrate/7adca3f86ebc8bcc926b6dc90f7589d2.png)
接下来看看int 16h如何读取键盘缓冲区。
![ce8a78139bc0acc588db316756f709ce.png](https://i-blog.csdnimg.cn/blog_migrate/058853381f2a03151d929588451f83ab.jpeg)
从上面可以看出,int 16h中断例程的0号功能,进行如下工作。
(1) 检测到键盘缓冲区是否有数据;
(2) 没有继续做第一步;
(3) 读取缓冲区第一个字单元中的键盘输入;
(4) 将读取的扫描码送入ah,ASCII码送入;
(5) 将已读取得键盘输入从缓冲区中删除。
于是我们就知道BOIS的int9中断例程和int 16h中断例程是一对相互配合的程序。int 9中断例程键盘缓冲区写入,int 16h中断例程从缓冲区中读出。它们写入与读出的时机不同,int 9中断例程是在有键盘按下的时候向键盘缓冲区中写入数据;而int 16h中断例程是在应用程序对其进行调用的时候,将数据从键盘缓冲区中读出。
字符串的输入,用户通过键盘输入的通常不仅仅是单个字符而是字符串。我们初步的了解一下。最基本的字符串输入程序,需要具备下面的功能。
(1) 在输入的同时需要显示这个字符串;
(2) 一般在输入回车符后,字符串输入结束;
(3) 能够删除已经输入的字符。
编写一个接收字符串输入的子程序,实现上面3个基本功能。因为在输入过程中需要显示,子程序的参数如下:
![cbc8c047b2f6be38975818d5d9e30fa3.png](https://i-blog.csdnimg.cn/blog_migrate/126dc361053e3af39d831962c3c4aeb4.png)
实际代码略。
应用int 13h中断例程对磁盘进行读写。3.5英寸软盘分为上下两面,每面有80个磁道,每个磁道又分为18个扇区,每个扇区的大小为512字节。
则:2面*80磁道*18扇区*512字节=1440KB≈1.44MB
磁盘的实际访问由磁盘控制器进行,我们可以通过磁盘控制器来访问磁盘。只能以扇区为单位对磁盘进行读写。在读写扇区的时候,要给出面号,磁道号和扇区号。面号和磁道号从0开始,而扇区从1开始。如果我们直接通过磁盘控制器来访问磁盘,则需要涉及许多硬件细节。BOIS提供了对扇区进行读写的中断例程,这些中断例程完成了许多复杂的和硬件相关的工作。我们可以通过调用BOIS中断例程来访问磁盘。
BOIS提供的访问磁盘的中断例程为int 13h.读取0面0道1扇区的内容到0:200的程序例:
![20a421f7b89004ffc47b4f08da3d1657.png](https://i-blog.csdnimg.cn/blog_migrate/117dce4a6b8811187d213ddd863f5a17.png)
入口参数:
(ah)=int 13h的功能号(2表示扇区)
(al)=读取的扇区数
(ch)=磁道号
(cl)=扇区号
(dh)=磁头号(对于软盘面号,因为一个面用一个磁头来读写)
(dl)=驱动器号 软驱从0开始,0:软驱A,1:软驱B;磁盘从80h开始,80h:硬盘C,81h:磁盘D
es:kx指向接收从扇区读入数据的内存区
返回参数:
操作成功: (ah)=0,(al)=读入的扇区数
操作失败:(ah)=出错代码
![dbe95313ebbf0c9e6decc244d9d406b4.png](https://i-blog.csdnimg.cn/blog_migrate/931ebd151cd6b7f1486b920495846849.png)
入口参数:
(ah)=int 13h的功能号(3表示扇区)
(al)=写入的扇区数
(ch)=磁道号
(cl)=扇区号
(dh)=磁头号(面)
(dl)=驱动器号 软驱从0开始,0:软驱A,1:软驱B;磁盘从80h开始,80h:硬盘C,81h:磁盘D
es:bx指向将写入磁盘的数据
返回参数:
操作成功: (ah)=0,(al)=写入的扇区数
操作失败: (ah)=出错代码
如果要使用int 13h中断例程对软盘进行读写。直接向磁盘扇区写入数据是很危险的,很可能覆盖掉重要的数据。如果向软盘的0面0道1扇区中写入了数据,要使用软盘在现有的操作系统下可以使用,必须要重新格式化。
用面号,磁道号,扇区号来访问磁盘不太方便。可以考虑对位于不同的磁道,面上的所有扇区进行统一编号。编号从0开始一直到2879,我们称这个编号为逻辑扇区编号。逻辑扇区号和物理扇区号的关系如下:
逻辑扇区号=(面号*80+磁道号)*18+扇区号-1
根据逻辑扇区号算出物理编号方法如下:
int():描述性运算符,取商
rem():描述性运算符,取余数
逻辑扇区号=(面号*80+磁道号)*18+扇区号-1
面号=int(逻辑扇区号/1440)
磁道号=int(rem(逻辑扇区号/1440)/18)
扇区号=rem(rem(逻辑扇区号/1440)/18)+1
本章结束,也是最后一章结束。当屏幕前的你看到这里的时候相信你对汇编语言已经有了一个全面基础的了解,如果你学过其他语言C,C++,JAVA都能看到汇编语言的影子。虽然现在在我们大多数人身边用到汇编的不多,但不影响汇编的思想在其他语言上一步步的继承发展。学无止境,如果你想知道更多的知识还是要坚持加油快乐的学习。
附注1
Intel系列微处理器的3种工作模式
(1) 实模式:工作方式相当于一个8086。
(2) 保护模式:提供支持多任务环境的工作方式,建立保护机制(这与VAX等小型机 类似)
(3) 虚拟模式:可从保护模式切换至其中一种8086工作方式。这种方式的提供使用户可以方便地在保护模式下运行一个或多个原8086程序。
任何一台Intel系列的CPU的PC只要一开机,CPU就是在工作在实模式下。如果是以前古老的DOS加载后CPU仍然是在保护模式下工作,因为windows是多任务系统,它必须在保护模式下运行,如果windows中运行一个DOS下程序,那么windows将CPU切换到虚拟的8086模式下运行该程序。
附注2补码
既然表示的书有符号,则必须要能够区分正负。采用一种称为补码的编码方式,这种思想是:先确定用00000000b~01111111b表示0~127,然后再用它们按位取反加1后的数据表示负数,
![989c97c85f5ede0c243f2fddf5e33984.png](https://i-blog.csdnimg.cn/blog_migrate/077ebfbce4524eb7554c5704e5f7a5af.png)
(1) 最高位为1,表示负数;
(2) 正数的补码反加1后,为其对于的负数的补码;负数的补码取反后加1后,为其绝对值。
补码为有符号数的运算提供了方便,运算后的结果依旧满足补码规则。