汇编实验15:安装新的int 9中断例程

任务

安装一个新的int 9中断例程,功能:在DOS下,按下“A”键后,除非不在松开,一旦松开后,就显示满屏幕的“A”,其他键照常处理。

预备知识概要

这次实验其实不难,王爽的教材中已经给出了许多实例代码,依葫芦画瓢都能圆满完成任务。

这次我们学习的是外中断,以外设的输入为例,CPU通过中断机制来处理外设的输入。

外中断源分为两大类:

  • 可屏蔽中断
  • 不可屏蔽中断

顾名思义,对于前者CPU可以选择不去响应中断,对于后者,CPU无论如何都要执行完当前指令后立即响应。

不可屏蔽中断的中断过程很容易理解,在8086CPU中,它的中断类型码是固定的,就是2,接下来的过程和内中断一模一样。

  • 标志寄存器入栈,并设置IF=0,TF=0
  • 将CS,IP寄存器压栈
  • 使(IP) = (8) ,(CS) = (0AH)

下面我们重点聊一聊可屏蔽中断

IF标志位

CPU通过IF标志为的状态来决定是否响应可屏蔽中断

  • 如果IF=1,CPU执行完当前指令后,响应中断,并引发中断过程
  • 如果IF=0,CPU不响应可屏蔽中断

我们可以通过以下两条指令设置标志位IF

  • STI 设置标志位IF = 1
  • CLI 设置标志位IF = 0

可屏蔽中断的中断过程

可屏蔽中断的中断过程和内中断的过程几乎一模一样,只不过取得中断类型码的方式不同,可屏蔽中断的中断类型码是通过数据总线进入CPU的。
为了表述完整,我还是总结一下这个中断过程(我怎么突然变勤快了吧,因为可以复制粘贴嘛!):

  • 获取中断类型码N(其实是为了获得中断例程的内存地址)
  • 标志寄存器入栈,并设置IF=0,TF=0
  • 将CS,IP寄存器压栈
  • 使(IP) = (4N) ,(CS) = (4N+2)

键盘输入过程

我们重点学习键盘输入的过程,总结起来就以下四步:

  • 键盘产生扫描码
  • 扫描码送入60h端口
  • 引发9号中断
  • CPU执行9号中断例程

键盘的每一个键相当于一个开关,按下一个键,开关接通,键盘上的芯片产生一个扫描码(大小为一个字节),我们称它为“通码”,来说明按键的位置,然后送入主板上相关的接口芯片的寄存器中,就是60H端口。
同样的,松开按键时,也会产生一个扫描码,然后被送入60H端口,这个扫描码被称为“断码”。

同一个按键有两个扫描码,就是断码和通码,它们的区别就是最高位1和0的差别。
可以总结为“断码 = 通码 + 80H”。

最后说一下BIOS的键盘缓冲区,它能存储15个键盘输入。每个键盘输入占用两个字节大小的空间。高字节放扫描码,低字节放字符码(就是ASCII码)。

代码实现

虽然是自己编写int 9中断处理程序,但是我们没必要完整的处理一个键盘的输入,中间涉及一些硬件细节,会偏离内容主线(总之就是现在的你太菜了,怕你伤自尊,就不告诉你了)。没关系,对于硬件细节的处理,交给BIOS的int 9的中断例程就好了嘛!

为此,王爽的书里就讲了一些技巧,比如怎么用汇编指令模拟int中断过程,怎么在已经修改了中断向量表的情况下,调用原始的BIOS的int 9中断例程。详细内容请见王爽的《汇编语言(第三版)》(我真的不想在打字了)

下面贴出我的代码:

  1. assume cs:code,ss:stack
  2. stack segment
  3. db 256 dup(0)
  4. stack ends
  5. code segment
  6. main: mov ax,stack
  7. mov ss,ax
  8. mov sp,256
  9. call install
  10. s: jmp s
  11. mov ax,4c00h
  12. int 21h
  13. ;********************************************************
  14. install: ;寄存器保护
  15. push ax
  16. push cx
  17. push si
  18. push di
  19. push ds
  20. push es
  21. ;将中断处理程序do9安装到内存单元0:204h
  22. push cs
  23. pop ds
  24. mov si,offset do9
  25. mov ax,0
  26. mov es,ax
  27. mov di,204h
  28. mov cx,offset do9end - offset do9
  29. cld
  30. rep movsb
  31. ;保存BIOS9号中断例程地址
  32. push es:[9*4]
  33. pop es:[200h] ;偏移地址存放到内存单元0:200h
  34. push es:[9*4+2]
  35. pop es:[202h] ;段地址存放到内存单元0:202h
  36. ;修改原来的中断向量表,此过程中不响应可屏蔽中断
  37. cli
  38. mov word ptr es:[9*4],204h
  39. mov word ptr es:[9*4+2],0
  40. sti
  41. ;恢复寄存器
  42. pop es
  43. pop ds
  44. pop di
  45. pop si
  46. pop cx
  47. pop ax
  48. ret
  49. ;----------------------------------------------------
  50. do9: push ax
  51. push bx
  52. push cx
  53. push es
  54. in al,60h
  55. pushf
  56. call dword ptr cs:[200h]
  57. cmp al,9eh ;A键的断码为9eh
  58. jne do9ret
  59. ;显示满屏幕的字符A
  60. mov ax,0b800h
  61. mov es,ax
  62. mov bx,0
  63. mov cx,2000
  64. do9_s: mov byte ptr es:[bx],'A'
  65. add bx,2
  66. loop do9_s
  67. do9ret: pop es
  68. pop cx
  69. pop bx
  70. pop ax
  71. ret
  72. ;----------------------------------------------------
  73. do9end: nop
  74. code ends
  75. end main

对,你没看错,这回的代码是有注释的!(我其实还是挺勤快的)。下面是执行的结果:

总结

这几次的实验其实都没有什么挑战性,都是依葫芦画瓢,只要熟悉教材前面的示范代码,都可以轻松的完成实验。关键就是对CPU中断机制和中断过程的理解。毕竟,在以后的学习中,我们不可能真的要自己用16位的汇编语言自己写一个中断处理程序(不然我选择狗带)。关键是对加深对计算机的理解,对汇编语言有个初步的认识与体验,为今后的学习作一定的铺垫(我其实挺想知道高级语言怎么编译成相应的机器指令的,可惜由于专业原因,这辈子都学不到了……可以自学……如果我不是个懒人的话……)。

汇编实验15:安装新的int 9中断例程的更多相关文章

  1. 汇编试验十五:安装新的int 9中断例程

    安装新的int 9中断例程(按'A'键后显示满屏幕的'A') int 9 是外中断,同样,程序编写还是和其他中断例程类似,安装(复制),调用: 不同点是在于,他要从端口读取数据60h, Source ...

  2. 实验十五_安装新的int 9中断例程

    安装一个新的int 9中断例程,功能:在DOS下,按下“A”键后,除非不在松开,    如果松开,就显示满屏幕的“A”:其他的键照常处理. 提示:按下一个键时产生的扫描码称为通码,松开一个键产生的扫描 ...

  3. 安装新的int 9中断例程2

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  4. 安装新的int 9中断例程

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  5. 汇编程序52:实验15 安装新的int9中断例程

    assume cs:code ;重写int9中断例程,当按住a后松开,便会产生满屏A stack segment dw dup() stack ends code segment start: mov ...

  6. [汇编学习笔记][第十三章int指令]

    第十三章int指令 13.1 int指令 格式: int n, n 为中断类型码 可以用int指令调用任何一个中断的中断处理程序(简称中断例程). 13.4 BIOS和DOS 所提供的中断例程 BIO ...

  7. x86汇编利用int 16h中断实现伪多线程输入

    x86汇编利用int 16h中断实现伪多线程输入 我们都知道,如果想让一个程序,同时又干这个,又干那个,最好的办法就是多线程.这个在高级语言里面已经用烂了. 但是,DOS是只有单线程的.我如果想让程序 ...

  8. 实验十三_编写、应用中断例程_2 & 总结

    编写并安装int 7ch中断例程,功能为完成loop指令的功能 参数:(cx)= 循环次数,(bx)= 位移 以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int.iret指令执行前后 ...

  9. 联想小新Air 15 安装黑苹果macOS High Sierra 10.13.6过程

    联想小新Air 15 安装黑苹果全过程 本文参考:https://blog.csdn.net/qq_28735663/article/details/80634300 本人是联想小新AIr 15 , ...

随机推荐

  1. Jquery的部分插件

    jQuery Easing:jQuery 动画效果扩展 jQuery Migrate:jQuery 应用迁移辅助插件Modernizr:专为HTML5和CSS3开发的功能检测类库jQuery Flex ...

  2. Python3基本数据类型(五、字典)

    一.定义 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号中: dic = {key: ...

  3. UVALive 6261 Jewel heist

    题意:珠宝大盗Arsen Lupin偷珠宝.在展厅内,每颗珠宝有个一个坐标为(xi,yi)和颜色ci. Arsen Lupin发明了一种设备,可以抓取平行x轴的一条线段下的所有珠宝而不触发警报, 唯一 ...

  4. ShellSort uva

    ShellSort He made each turtle stand on another one's back And he piled them all up in a nine-turtle ...

  5. VOJ1067 【矩阵经典7 构造矩阵】

    任意门:https://vijos.org/records/5be95b65d3d8a1366270262b 背景 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条 ...

  6. HttpHandler使用Session

    继承自IHttpHandler的类要实现两个接口:ProcessRequest和IsReusable但还不能使用Session,要使用Session需要下面的步骤处理: 1.先引用System.Web ...

  7. Android学习笔记_74_Android回调函数触发的几种方式 广播 静态对象

    一.通过广播方式: 1.比如登录.假如下面这个方法是外界调用的,那么怎样在LoginActivity里面执行登录操作,成功之后在回调listener接口呢?如果是平常的类,可以通过构造函数将监听类对象 ...

  8. MapFile

    MapFile是排序后的SequenceFile, 这个排序是由开发者来保证的, 不是内存实现. 相当于对key作了一个分块索引,  只针对key. 缺点 1.文件不支持复写操作,不能向已存在的Seq ...

  9. C语言输出格式

    1 一般格式    printf(格式控制,输出表列)    例如:printf("i=%d,ch=%c\n",i,ch);    说明:    (1)“格式控制”是用双撇号括起来 ...

  10. 简单实用的.htaccess文件配置

    .htaccess 文件 (Hypertext Access file) 是Apache Web服务器的一个非常强大的配置文件,对于这个文件,Apache有一堆参数可以让你配置出几乎随心所欲的功能.. ...