汇编语言中断及外部设备操作篇--06

x33g5p2x  于2022-06-24 转载在 其他  
字(3.8k)|赞(0)|评价(0)|浏览(647)

本系列文章参考汇编语言第四版和汇编语言程序设计 贺利坚主讲整理而成

移位指令

示例:逻辑移位指令shl和shr

操作显存数据

显示的原理

显示缓冲区的结构

显示信息的一种“直接”方式

描述内存单元的标号

关于标号

上面的写法需要用offset来指明代码段中数据的地址

去了冒号的数据标号

a[si]---->[si+a]

数据标号同时描述内存地址和单元长度

mov al,b报错是因为b操作的内存单元是字大小,而al是字节大小,不符合

更常见的方式:数据段中的数据标号

上面都是将数据放在了代码段中,但是一般都是各段分隔开来存放。

如果将数据标号当做数据来定义,那么对应保存的是这个数据标号指向的内存地址

a db 123
b dw 0
#c标号指向内存单元,保存了两个字数据,一个是a标号指向的内存偏移地址,另一个是b标号指向的内存偏移地址
#此时c可以看做是指针的指针
c dw a,b
a db 123
c dw 0
#c表示指向内存单元,保存了两个双字数据,对于每个双字数据而言,前一个保存了对应偏移地址,后一个保存了对应段地址
c dd a,b

当我们将数据标号作为数据定义的时候,是不是特别类似C语言中的指针的指针

数据的直接定址表

直接定址表:用查表的方法解决问题

最简解决方案

00101011 是作为低字节存放在al中的,其中前后四位各组成0-15中一个数字,然后去字符表中定位对应的位置的字符
  • 因为最小操作单位是字节,所以将ah保存al的高四位,通过右移四位完成,而al保存低四位,通过一个与运算完成

直接定址表

应用示例:为加快运算速度而采用查表方法

解决方案

  • 首先使用一张表记录每个角度对应的sin值,上面使用了数据标号的方式,相当于 table dw ag0…中ag0存放的是sin0对应值的偏移地址(指针指向指针)
  • 预备动作: 将将会使用到的寄存器状态入栈,然后es附加段寄存器的段地址指向显存空间
  • al存放角度,bl存放除数30,然后进行除法运行,由于是8位除法,因此商会被保存在al中,余数被保存在ah中,这里我们只关心商
  • 将商保存到bl中,bh置空,此时bl中存放的就是偏移地址,但是单位是字节
  • bx需要变为两倍,因为上面table表的单位是字,而这里是字节
  • 从table表中根据偏移地址,取得对应字符串的偏移地址,因为这里是数据标号指向数据标号,可以看做是指针指向指针,指针的值就是他执行的内存地址
  • 通过bx中保存的字符串偏移地址,定位到对应的内存地址,然后挨个字节依次输出,直到遇到0为止
  • 恢复相关寄存器的状态

代码的直接定址表

使用代码的直接定址表解决问题

各种功能的实现

这里重点关注的不在是各个功能的具体实现了,而是主程序中通过查表得到每个子程序开始的地址,这个操作是如何完成的

  • 通过在ah中设置需要执行的子程序在表中的相对偏移地址,但是ah保存的偏移地址单位是字节,而表单位是字,因此还需要*2,得到子程序在表中真实的偏移地址

直接写址表的优势

查表可以提高速度,并且可以使程序架构非常清晰易懂,也便于程序扩充。
查表的思想与策略模式类似,都是用来解决一堆IF...ELSE判断的

中断及其处理

中断的概念

8086的内中断

中断处理程序

  • 因为8086CPU的中断向量表中,每个中断程序占据四个字节,前两个字节保存中断程序代码段的偏移地址,后两个字节保存中断程序代码段的段地址。

并且因为每个中断程序占据四个字节,因此IP与N是有规律可循的,IP=N4,CS=N4+2

当发生中断时,先查表得到中断程序的地址,然后设置CS和IP的值即可去执行中断程序

案例:系统中的0号中断

当发生除法错误时,触发0号中断,此时会去查表得到0号中断程序的地址,然后设置CS和IP指向中断程序地址,然后执行中断程序

中断过程

执行中断程序前需要先保护现场,这点很重要,主要是保存标志寄存器的状态和当前程序的地址

编制中断处理程序

中断处理程序及其结构

编制中断处理程序——以除法错误中断为例

do0子程序应该放在哪里?

程序框架

安装程序就是把程序代码送入到先前指定存放程序的内存空间中去,然后更改中断向量表0号表项存放的0号中断程序的地址即可。

do0安装程序的实现

程序占用的总共字节数,可以通过两个地址标号表示地址直接差值算出来

do0子程序的实现

显示字符,就是将对应字符写出到显示缓冲区即可,然后设置中断向量表就是将do0中断程序的入口地址,写入到中断向量表的0号表项中

因为do0中断程序中mov ax,4c00h int 21h会直接结束程序运行,返回DOS系统,因此并不会在中断程序执行结束后,返回原有程序继续执行。

小结

单步中断

由Debug中的t命令说起……

单步中断过程与处理

应用:中断不响应的情况

如果在执行向ss寄存器传送数据的指令时,发生了中断,那么CPU会将相关中断寄存器值设置为0,不允许中断产生,这样下一条指令会继续执行,执行完下一条指令后,再进入中断

因此右边的写法是错误的,因为这样写的话,mov ss,ax和mov ax,0会一起连续执行,而mov sp,10指令会单步执行

由int指令引发的中断

int n引起的中断

编写供应用程序调用的中断例程

示例 :中断7ch的中断例程

在执行int n中断之前,会把当前CS和IP寄存器状态入栈,还有标志寄存器状态入栈,然后中断例程执行结束后,再将相关状态出栈,进行现场还原。

如果中断程序中使用到了相关寄存器,也需要在使用前保存对应寄存器状态,程序结束后恢复

BIOS和DOS中断处理

BIOS——基本输入输出系统

BIOS中断调用示例

有哪些BIOS中断,怎么用?

汇编的强大功能,还有DOS中断!

int 21HDOS 中断例程的应用

BIOS和DOS中断例程的安装过程

端口的读写

用端口访问外设:以发声为例

CPU的邻居

CPU通过这些端口控制各种芯片的行为,这些端口实质就是寄存器,但是是与对应芯片相关的寄存器,不是cpu内部从寄存器,这些芯片通过读取这些寄存器的值,知道自己应该干什么

端口的读写

端口的读写过程演示

in al, 20h 
out 21h, al

I/O端口分配

端口的读写指令示例

操作CMOS RAM芯片

CMOS RAM 芯片

端口操作示例:提取CMOS RAM中存储的时间信息

在屏幕中间显示当前的月份

外设连接与中断

CPU通过端口与外部设备“连接”

外中断:由外部设备发生的事件引起的中断

外中断处理过程

PC机键盘的处理过程

PC机键盘的处理过程

键盘上键的扫描码(通码)

PC机键盘的处理过程——引发中断

控制键和切换键由键盘状态字节负责存储,该字节每一位都代表一个按键的状态

PC机键盘的处理过程——执行中断例程

输入 ‘a’ 的处理过程

定制键盘输入处理

PC机键盘的处理过程(int 9 中断例程)

实现:依次显示’a’~‘z’(v0.2)

空循环的设计给出一个思路:dx和ax都赋值一个最大值,然后先把ax寄存器的值减到0结束,结束后再把dx的值也减到0

实现:依次显示”a”~”z”(v0.4)

按下 Esc 键后改变显示的颜色

实现: 按下 Esc 键后改变显示的颜色(v1.0)

在轮询显示a–z的过程中,按下任何键,如果触发了中断,首先会去调用其原本的中断例程,原本的中断例程执行结束后,如果按下的是ESC键还会去额外改变当前显示字体的颜色,如果是其他键,就没有额外的功能了

改写中断例程的方法

改写中断例程-以int 9为例

实现方法

  • 安装新程序是先计算出int9和int9end数据标号之间的字节差值,即等于程序的大小,然后循环拷贝所有字节到0:204h处
  • 将原先中断地址保存到2:200单元处
  • 将int9中断调用的中断例程变为我们新写的中断例程地址,即0:204h,并且这个过程要保证不被可屏蔽中断打断,通过cli设置完成,结束后,再允许被打断,通过STI完成
  • 程序返回

用中断响应外设

如何操作外部设备?

对键盘输入的处理的int 9h中断和int 16h中断

演示:输入A、B、C、D、E、Shift_A、A 引发的(int 9)“动作”

上面是输入完ABCDE后的,键盘输入缓冲区的状态,下面输入SHIFT_A

此时我们再按下一个A

Shift标志为还原

演示int 16h

用int 16h读取出 用int 9h存入缓 冲区的数据

键盘缓冲区的实现

  • 共16字
  • 用环形队列
  • 可存储15个按 键扫描码

依次从键盘缓冲区读取出一个字,放入数据缓冲寄存器,然后再放入AX中,AH存放扫描码,AL存放ASCII

调用int 16h 从键盘缓冲区中读取键盘的输入

应用示例:更改屏幕颜色

应用:字符串的输入

要解决的问题

程序的处理过程

子程序:字符栈的入栈、出栈和显示

实现字符栈的入栈、出栈和显示

当一个程序中存在若干子功能的时候,一般不采用挨个判断方式,而采用查表法来决定当前应该调用哪一个子功能

读写磁盘

如何操作磁盘?

BIOS提供的磁盘直接服务——int 13h

用BIOS int 13h对磁盘进行读操作

用BIOS int 13h对磁盘进行写操作

DOS中断对磁盘文件的支持——int 21H

让计算机“唱歌”

外部设备与如何被控制的?

程序可以直接访问外设,是通过端口的形式进行访问的

与"计算机唱歌"有关的硬件及控制

让计算机唱歌,需要与8253和8255芯片打交道,而CPU想要控制这两个芯片,需要通过对应两个芯片提供的端口进行操控

因为进行了统一编址,所以我们可以很容易定位到这两个端口的地址都是什么,然后通过in和out指令写入数据操作它,获取从对应的端口读取出我们需要的数据。

“翻译”乐谱

演奏程序

相关文章

目录