9.6 基于中断的功能调用

计算机组成

9 中断和异常

9.6 基于中断的功能调用

那现在,我在执行这些运算之后,也就是执行这些程序的过程中呢,又遇到了一个奇怪的现象。这里突然有一个地方写着,请查看紧急操作手册的第二百项,那我就翻到这个地方去了。翻到前面,然后找第二百项,然后找到了对应的操作——是让我在本子的某一个地方写一个数。这是怎么回事呢?一般来说,刚才我们学到的都是我在运算当中遇到了异常的情况,然后我主动去查找前面的对应的异常处理的方法,查找中断向量表。那么现在在这个程序当中,居然主动的写到了让我去查找相关的中断项量表。这个是怎么回事情呢?我们就来看看这个问题。

在x86指令系统当中,其实还提供了一条中断指令,它的格式是INT,加上一个操作数n。用这条指令,就可以直接调用对应的中断服务程序。这个n是0到255当中的一个数,对应的中断类型码。当CPU执行到指令时,首先会将标志寄存器压栈,然后清除IF和TF两个标志位,也就是关中断。再将CS和IP两个寄存器的内容压栈,然后根据指令中提供的类型码,也就是这个n,去查找中断向量表,找到对应的中断服务程序的入口地址。再将入口地址装到CS和IP寄存器当中去,这样下一步CPU就会到中断服务程序的入口取出下一条指令继续执行。

那么看到这一个步骤和我们之前介绍的,CPU处理中断的过程是一样的。但是区别在于,这是由运行指令主动触发的。

比如,之前CPU当中,如果发生的1号中断,CPU就会来中断向量表当中取出1号中断向量。然后,转向对应的中断服务程序开始执行。但如果当前CPU执行程序的过程当中,并没有满足触发1号中断的条件,而是直接写了一条指令 int 1,CPU也会到中断向量表当中,取出1号中断向量,装入CS,IP寄存器,再转到1号中断服务程序开始执行。

那这样做有什么意义呢?明明没有发生中断,我们为什么要调用这个中断服务程序。这种中断指令的使用场景其实有两类。一类就是CPU的一些专用的中断,就是需要通过调用指令的方式来实现的。比如说3号中断,那就得写 int 3 这样的指令才可以产生。这种情况我们在之前已经介绍过了,现在我们来看另外一种情况。

比如说有一类,我们称为BIOS中断。BIOS就是基本输入输出系统,这是一套不大但是还挺复杂的程序,存放在ROM当中。寄存器在刚通电或者复位时,CPU就会从BIOS ROM当中取出第一条指令开始执行。所以,在BIOS当中会提供系统加电自检和主要的输入输出设备处理程序等功能模块。所谓的功能模块,也就是一个一个具有独立功能的程序,比如从键盘接收一个字符,或是在显示器上显示一个字符,这些工作不但在系统初始化时需要使用,在后来用户使用计算机的过程中,其实也会用到。而如果要用户自己去编写处理这些输入输出设备的程序,那就太麻烦了。所以,BIOS的设计者就将其中的这些功能各个包装起来,形成了很多个独立的功能模块。然后将这些独立功能模块的入口地址,放在中断的向量表当中,那如果我们想使用这些功能,比如说就像在显示器上显示一个字符,用户就不用去关心到底用的是什么显示器,要占用多少个像素,等等。只需要使用BOIS提供的功能模块,用INT指令调用对应的中断服务程序就可以了。而且我们可能希望向这些功能模块传递一些参数,那就可以通过寄存器进行传递。

我们不妨来看一个例子。

这个表是BIOS中断的一个片段。想使用BOIS中断,首先就得查找BIOS中断的手册,这个手册一般会提供这样一个表格,列出了BIOS这些功能模块所在用的中断号,比如说10H,就是用于在显示器上进行显示的一个中断服务程序;而1AH,则是设置系统时钟的一个中断服务程序。

我们以1AH为例。如果我们想要改变现在的系统时钟,当然我们可以去分析时钟管理芯片的功能,通过查找它的手册来分析如何去改变系统时钟的设置,这可能要花很多个步骤。那BIOS的设计者就帮我们封装好了这个功能,我们只要这样写代码就可以了(红色汇编代码)。因为我们通过这个表可以看到,如果要设置时钟,我们需要提供一个功能号为1,因为1AH这个中断里头,其实有多种功能,我们可能想读出当前时钟的值;也可能要改变当前时钟的值。这个中断服务程序怎么识别呢?

它就要求你在AH寄存器当中放入一个数,那么在中断服务程序的开始,会先检查AH寄存器。如果里面是0,那它就按照读时钟的操作运行后续的代码;如果AH里面的值是1,它就按照设置时钟的操作执行后续的代码。

现在我们要设置时钟。所以,在AH里面先放上1。然后我们查这张表,知道我们要设置的时间是放在这几个寄存器当中,CH放在要设置的小时数,CL放要上要设的分钟数,DH是秒,DL是百分之一秒。而CL和CH组成的寄存器是CX,DL和DH组成的寄存器是DX。所以,我们直接可以通过对CX和DX赋值,来设置这个时间。那么现在为了简单,我们就设成0点0分0秒,这些参数准备好以后,我们最后写 INT 1AH

接下来就像是之前介绍过发生中断的时候一样,CPU会去中断向量表当中找到1AH对应的中断向量,然后转移到对应的中断服务程序开始执行,而这段中断服务程序就是位于BIOS所在的存储区域。那在这个中断服务程序当中,就会去操作管理系统时钟的芯片或者部件完成时钟的更改,然后再返回到这个主程序当中继续执行下面的代码。

这样就把一个和底层硬件细节非常相关的操作给封装起来,让编程人员可以比较轻松的完成这样的工作。BIOS中断其实提供了很多种类型,可以完成相当丰富的功能,有兴趣的话,可以查找相关BIOS的手册。但是因为BIOS容量有限,因此我们还是可以利用这个方法,在上层的软件当中,提供更为丰富的功能。

那我们来介绍一个例子,就是DOS中断。

DOS是早期的一种操作系统。它占用了一个中断类型号,21H。和BIOS占据了多个中断类型号不同,DOS中断只有这一个类型号。但它的功能非常的丰富,常用的文件管理、 存储管理等很复杂的功能,都可以用这个中断服务程序来解决。那它怎么区分我们到底想使用哪个功能呢?其实刚才BOIS中断给我们提供了这样的思路。我们可以通过一个寄存器,传入一个参数,来告诉中断服务程序,我们到底想调用哪样的功能。所以,所有的DOS中断都只使用这一个中断入口。而且DOS是一个操作系统,它所提供的中断功能比BIOS中断更为齐全、完整,而且进一步屏蔽了设备的物理特性,让编程的使用变得更加的方便。

我们也来看一个例子。如果我们想在屏幕上输出一个字符,那我们可以查找DOS中断所提供的表格,DOS中断都是21H。所以,这个表里面只需要列出功能号。那么发现,6号功能是在进行输入输出的操作。所以,我们现在AH寄存器当中存入6。然后我们进一步发现,如果我们想输出一个字符,就在DL寄存器当中,放入我们想显示的这个字符;而如果我们想通过键盘输入这个字符,则只需要在DL寄存器当中,存入FF。而最后输入的字符,会放在AL寄存器当中。那我们现在还是来看输出,所以我们在DL寄存器当中存上这个字符,然后调用 INT 21H, 这样CPU就会转向21H号中断所对应的中断服务程序。在这个服务程序当中,首先会检查AH里面的值,确定功能号,然后就进入到这个功能对应的程序代码段,再根据DL寄存器的内容,判断出这是一次输出。那这个服务程序接下来就会对显示器进行操作,让对应的字符显示在屏幕的合适的位置。

这些繁琐的工作,都不需要用户来关心了,只要简单的调用这个DOS中断就可以了。当然前提是这些操作都已经由其它的程序员帮你写好,并且封装起来还安装在了你这个电脑上,这样你才可以使用。归根到底,这些操作都还是要有人来写出程序,只不过一次写好之后,其他的用户就可以直接调用了,这样会很方便。所以说,无论是BIOS中断,还是DOS中断,或者是其它类似的中断方式,其本质并不是计算机运行当中发生了异常的情况,而是利用了现有的中断这种机制来实现一些系统函数,代码的调用,以便向高层的软件屏蔽底层硬件的细节,从而提高编程的便利性,正确性和可移植性。

那现在,我们的机制已经讲的很清除了。在程序执行的过程中遇到的任何异常情况,我们都可以自如的处理,而且还可以利用这个机制,完成更加丰富的功能。所以,可以说我们对任何情况,都已经是能够应对自如了。

原文地址:https://www.cnblogs.com/doctorx/p/9743786.html

时间: 2024-11-08 21:27:38

9.6 基于中断的功能调用的相关文章

x01.os.5: DOS 功能调用

DOS 功能调用(INT 21)-------------------------------AH = 0-2E 适用 DOS 1.0 以上版本AH = 2F-57 适用 DOS 2.0 以上版本AH = 58-62 适用 DOS 3.0 以上版本------------------------------- AH = 00功能:程序终止(同 INT 20h)调用参数: CS = 程序段前缀 AH = 01功能:键盘输入并回显返回参数: AL = 输入字符 AH = 02功能:显示输出调用参数:

汇编相关(ASCII码字符表 DEBUG命令 BIOS功能调用表 DOS功能调用表 汇编语言错误信息表)

汇编相关 一些关于汇编的常用东西,包括: ASCII码字符表 DEBUG命令 BIOS功能调用表 DOS功能调用表 汇编语言错误信息表 ASCII码字符表 DEBUG命令 BIOS功能调用表 DOS功能调用表 汇编语言错误信息表

按中断的功能来分,中断有哪几种类型?

按中断功能分类: 1.输入输出中断 2.外中断 3.机器故障中断 4.程序性中断 5.访管中断 补充: 一般中断按功能.中断方式.终端来源分类 按中断方式分类 1.强迫性中断 2.自愿中断 按中断来源分类1.中断 2.俘获

基于反射的动态调用-不止是code和oop,还有类加载方案

先给出基础类资源的代码,很容易理解,不做过多介绍: 1 package oop; 2 interface t { 3 public static final String name="zhangph"; 4 } 5 public class Father implements t{ 6 private static int mem; 7 static { 8 System.out.println("这是父类");//因为你不曾常用反射,所以加上这段代码显示区别 9

基于docker的php调用基于docker的mysql数据库的方法

1:建立基于docker的mysql,参考 Mac上将brew安装的MySql改用Docker执行 2:建立基于docker?php image 在当前目录,建立Dockerfile,内容如下 FROM php:7.0-cli MAINTAINER Terry Zhang <[email protected]> RUN docker-php-ext-install pdo_mysql mysqli 3.建立php镜像 docker build -t php-mysql . 4. 编写php脚本

DOS功能调用——单个字符及字符串的输入输出

DOS系统功能调用步骤:    1. AH <- 功能号    2.指定寄存器放入该功能所要求的入口参数    3.执行int 21H    4.分析出口参数 单字符输入输出 01h键盘输入            AL=输入字符    02h显示器输出            DL=输出字符    07h直接控制台输入(无回显)    AL=输入字符    08键盘输入(无回显)        AL=输入字符======================汇编例子===================

C# Winfrom小黄鸡功能调用

最近研究微信公众平台,搭建了一个微信聊天机器人,调用小黄鸡的公众接口,实现在线和小黄鸡聊天的功能. 接口调用不是很麻烦,不过是php版本,所以研究了一下C#的功能模块, Winfrom版 后台界面代码为 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq;

Android图片裁剪功能——调用系统裁剪

花了两天时间看了下android的图片裁剪功能的实现.其实刚开始做这个我挺虚的,以为整个功能都需要自己写出来,但查了些资料,发现android已经提供了裁剪功能,需要的话自己调用就成了.soga,这下轻松多了. 首先推荐几篇博客 Android大图片裁剪终极解决方案 要想弄明白裁剪功能,这系列博客非常重要,你可以不看我下面总结的,但你一定要看他这系列的几篇文章. Android 图片裁剪功能实现详解(类似QQ自定义头像裁剪) 这篇也不错,比较喜欢他的注释.虽然也有些误导,比如说他有一段对setD

大话IDL编程之函数功能调用(envi_doit、ENVIRaster、ENVITask)

2020年2月1日.好长时间没更新博客,还真有点不习惯.受新型冠性病毒的影响,平时街上熙熙攘攘的人流了无踪影,2020的春节竟然来的如此冷清.为响应“呆在家里就是做贡献的号召”,在家一宅就是十多天.闲来无事,就总结一下ENVI-IDL二次开发的学习经验吧. ENVI二次开发主要有两种编程方式:IDL二次开发.ENVI-IDL交互式开发. 其中,IDL二次开发方式较为繁琐,但是也的确算是基本功,需要熟练掌握.而ENVI-IDL交互开发的方式简洁高效,是现在的主流开发方式. 其中,对于某些功能函数,