目录
了解printf, scanf的执行过程。
。。。
看完了教程以后,对第一代工程师佩服的五体投地,用汇编操作屏幕,鼠标,文件IO,内存,需要极强的耐心,
也许他们那个时代只有这种语言,所以能学的很彻底吧。主要做个了解吧。
另外很多端口地址都是不可能硬记的,还是要靠百度一下,现查现用。
先看一下问题
一,基本概念
1,I/O端口地址
每次可交换一个字节数据的端口称为字节端口,每次可交换一个字数据的端口叫字端口。
在Intel公司的CPU家族中,I/O端口的地址空间可达64K,即可有65536个字节端口,或32768个字端口。这些地址不是内存单元地址的一部分,不能普通的访问内存指令来读取其信息,而要用专门的I/O指令才能访问它们。虽然CPU提供了很大的I/O地址空间,但目前大多数微机所用的端口地址都在0~3FFH范围之内,其所用的I/O地址空间只占整个I/O地址空间的很小部分。
计算机在启动时,bios程序(basic input/output system)将检查计算机系统中有哪些端口地址。当发现有串行端口地址时,bios就把该端口存放在以地址40:00h开始的数据区内;当发现有并行端口地址时,bios就把它存入以地址40:08h开始的数据区内。每类端口有4个字的空间。对有两个串口,两个并口的计算机系统,bios分布表如图
2,I/O指令
由于端口地址和内存单元地址是相互独立的,这些端口地址不能普通的访问内存指令来访问其信息,所以,在cpu的指令系统中,专门设置了I/O指令来存取I/O端口信息。
按功能分类,属于数据传送指令。
1)输入指令 in
格式:
in al/ax, portNo/dx
作用:从端口中读入一个字节或者字,并保存在al或ax中。如果某输入设备的端口地址在0~255范围内,那么可在指令in中直接给出,否则,要把该端口地址先存入寄存器dx中,然后在指令中由dx来给出其端口地址。
2)输出指令 out
格式:
out protNo/dx, al/ax
该指令的作用是把寄存器AL或AX的内容输出到指定端口。如果某输出设备的端口地址在0~255范围之内,那么,可在指令OUT中直接给出,否则,要把该端口地址先存入寄存器DX中,然后在指令中由DX来给出其端口地址。
#回顾字符串输出指令lods, stos, movs, ins, outs, cmps, scas, rep, repe(带条件)。
二,中断
1,概念
响应中断取决于3个条件:
1)有中断请求;
2)允许cpu接受中断请求;
3)一条指令执行完,吓一跳指令还没开始执行。
2,中断向量表和中断服务程序
1)中断向量表是一个特殊的线性表,它保存着系统所有中断服务程序的入口地址(偏移量和段地址),在微机系统中该向量表有256个元素,每个元素4字节。共1k。(具体的要百度查)
3,引起中断的指令
1,中断指令 int
格式:
int imm ;立即数imm是一个0~0ffh范围内的整数(256)
指令执行的步骤:
1)把标志寄存器压栈,清除标志位if 和 tf;
2)把代码段寄存器cs的内容压栈,并把中断服务程序入口地址的高字部分送cs;
3)32位段,压32位ip。
一个中断可有很多不同的功能,每个功能都有一个唯一的功能号,中断的功能号由ah来决定。
例如:
2,溢出指令 into
概念:当标志位of为1时,引起中断, 该指令影响的标志位 if 和 tf.
3,中断返回指令 iret / iretd
格式: iret/iretd
操作步骤是int逆过程:
1)从栈顶弹出内容送入ip;
2)再从新栈顶弹出内容送入cs;
3)再从新栈顶弹出内容送入标志寄存器。
4,和子程序的比较
它们的主要差异有: | |
子程序调用一定是程序员在编写源程序时事先安排好的,是可知的,而中断是由中断源根据自身的需要产生的,是不可预见的(用指令INT引起的中断除外); | |
子程序调用是用CALL指令来实现的,但没有调用中断的指令,只有发出中断请求的事件(指令INT是发出内部中断信号,而不要理解为调用中断服务程序); | |
子程序的返回指令是RET,而中断服务程序的返回指令是IRET/IRETD。 | |
在通常情况下,子程序是由应用系统的开发者编写的,而中断服务程序是由系统软件设计者编写的。 |
三,中断的分类
可分为
1)硬件中断,软件中断(int, into)
2)可屏蔽中断(cli, sti),不可屏蔽中断。
在用户程序中,若直接通过端口来操作硬件或外设,那么,其处理过程没有额外的多余工作,处理速度显然是最快的,但这样做,无疑使用户程序具有了很大的局限性。硬件环境的改变将直接影响程序的正常运行。
若用户程序通过调用DOS功能来实现其所需功能,那么,应用程序与低层硬件相距较远,操作最终的对象需要经过中间环节,处理速度肯定受到一定的损失,但这种应用程序适应性强,应用范围广,对硬件的依赖性最小。
1,键盘输入的中断
1,键盘缓冲区
1)概念:是一个环形队列。
2)键盘状态字
在计算机键盘上除了可输入各种字符(字母、数字和符号等)的按键之外,还有一些功能键(如:F1、F2、…等)、控制键(如:Ctrl、Alt、Shift等)、双态键(如:Num Lock、Caps Lock等)和特殊请求键(如:Print Screen、Scroll Lock等)。
键盘中的控制键和双态键是非打印按键,它们是起控制或转换作用的。当使用者按下控制键或双态键时,系统要记住其所按下的按键。为此,在计算机系统中,特意安排的一个字来标志这些按键的状态,我们称该字为键盘状态字。
3)键盘中断的处理过程
了解就行,截图如下
2,屏幕显示的中断功能
1,显示模式
1)文本显示方式
2)图形显示方式
1,举了3个例子,
2,显示缓冲区
3,两个练习题
3,打印输出的中断功能
概念:硬拷贝。
例题,打印字符串 (bios 17h实现打印功能)
4,串口的中断功能
bios提供14h作为控制中断,具体参数如下
功能描述: | 初始化通信口 | |||||||||||||||||||||||
入口参数: | AH=00H
对于PS/2,可用INT 14H之功能04H和05H来初始化其通信速率大于9600。 | |||||||||||||||||||||||
出口参数: | AH=通信口状态,各状态位为1时的含义如下:
AL=Modem状态
|
| 功能描述: | 向通信口输出字符 |
入口参数: | AH=01H | |
出口参数: | AL的值不变 |
| 功能描述: | 从通信口读入字符 |
入口参数: | AH=02H | |
出口参数: | AL=接受的字符 |
| 功能描述: | 读取通信口状态 |
入口参数: | AH=03H | |
出口参数: | AH=通信口状态,AL=Modem状态,参见功能号00H中的说明 |
两个例题
(看到这里,不得不佩服第一代程序员工程师,用汇编操作这些东西简直要命,需要极强的耐心)
5,鼠标的中断功能,略过了。
6,目录和文件的中断功能
中断21H提供了许多有关目录和文件操作的功能,其中常用的功能如下:
1、操作目录的常用功能
| 39H——创建目录 | 3BH——设置当前目录 |
3AH——删除目录 | 47H——读取当前目录 |
2、用文件句柄操作文件的常用功能
| 3CH——创建文件 | 4EH——查找到第一个文件 |
3DH——打开文件 | 4FH——查找下一个文件 | |
3EH——关闭文件 | 56H——文件换名 | |
3FH——读文件或设备 | 57H——读取/设置文件的日期和时间 | |
40H——写文件或设备 | 5AH——创建临时文件 | |
41H——删除文件 | 5BH——创建新文件 | |
42H——设置文件指针 | 67H——设置文件句柄数(最多文件数) | |
43H——读取/设置文件属性 | 6CH——扩展的打开文件功能 |
3、用FCB操作文件的常用功能
| 0FH——打开文件 | 21H——随机读 |
10H——关闭文件 | 22H——随机写 | |
13H——删除文件 | 23H——读取文件的大小 | |
14H——顺序读 | 24H——设置相对记录数 | |
15H——顺序写 | 27H——随机读块 | |
16H——创建文件 | 28H——随机写块 | |
17H——文件换名 |
4、磁盘绝对读写中断
| 中断25H——磁盘绝对读中断 | 中断26H——磁盘绝对写中断 |
5、系统标准设备的句柄
| 0000H——键盘 | 0001H——屏幕 |
0002H——错误显示(屏幕) | 0003H——COM1 | |
0004H——打印机 |
两个例题,文件操作
7,内存管理的中断功能
在C/C++语言环境中,若事先不知道数据的容量,那么,可通过动态申请空间的方法来解决数据的存储问题,这种动态数据结构可用中断21H所提供的存储管理功能来实现。
中断21h再内存管理方面所提供的主要功能如下:
8,读取和设置中断向量
中断向量是系统用来存放中断服务程序或系统参数的入口地址。在通常情况下,程序员不需要对中断向量表作任何操作,但在开发程序时,若要为某种特殊需要而提供新的中断处理程序时,则其就必须要操作中断向量表。
1)读取中断向量
dos:
其中断21H之功能35H就能读取指定中断号的入口地址。其使用参数如下:
入口参数: ah = 35h, al = 中断号
出口参数:es:bs = 中断处理程序的入口地址
直接访问存储单元的方法
2,设置中断向量
dos
中断21H之功能25H可为指定的中断号设置新的入口地址。其使用方法如下:
入口参数: ah = 中断号, ds:dx = 中断处理程序的入口地址
出口参数:无
直接访问存储单元的方法
3,修改中断向量的步骤
1)读取指定中断的中断处理程序入口地址,并把它保存在存储单元内。
2)把用户编写的程序段设置位指定中断的新处理程序;
3)在用户程序结束之前,把步骤1保存的入口地址恢复成处理该中断的入口地址。
程序员按以上三步来编程,可保证:在其程序运行过程中,该指定的中断将按新的处理程序来处理,程序结束后,中断系统又恢复成原来的处理方式。所以,这种中断向量的改变对其它程序或使用者来说是透明的,当然也就不会影响它们的正常运作。