汇编语言中的外中断——键盘事件
来源:互联网 发布:台湾人淘宝 编辑:程序博客网 时间:2024/05/16 11:47
汇编语言中的外中断和内中断差不多
1、取中断类型码n
2、标致寄存器入栈,IF=0,TF=0
2、CS、IP入栈
3、(IP)=(n*4),(CS)=(n*4+2)
但是外中断和内中断的中断类型码的来源不同,所以第一步肯定是不一样的,其他相同
下面来讲一下键盘事件下的处理方式
只要有键盘事件发生,就会触发int 9,这个int 9是硬件扫描过程,其实就是CPU对按键的IO口进行扫描的过程
这里问题就出现了,因为键盘事件发生必定会引发int 9,所以如果要对按按键后进行处理的话,需要将中断程序写在int 9中,但是如果需要扫描键盘的按键,就必须要调用BIOS提供的int 9
解决这种冲突的办法就是先将BIOS提供的int 9的IP和CS储存起来,用模拟int指令的方式来调用原来的int 9,当然新建的int 9需要将其入口的IP和CS放到向量表中
任务:显示a~z,按下ESC结束
代码:
assume cs:codedata segment ;储存原int9的IP和CSdw 0, 0data endscode segmentstart:mov ax, 0 ;将原int9的IP和CS放到data空间中mov ds, axmov ax, datamov es, axpush ds:[9*4]pop es:[0]push ds:[9*4 + 2]pop es:[2]mov ax, 0 ;将新的int9中断的IP,CS写入中断向量表中mov ds, axmov word ptr ds:[9*4], offset do9hmov word ptr ds:[9*4 + 2], csmov ax, 0B800Hmov ds, axmov al, 'a'mov cl, 2s:mov ds:[10*160 + 8*2], almov byte ptr ds:[10*160 + 8*2 + 1], clcall delay ;调用延时的子程序,方便显示cmp al, 'z'je s0inc aljmp ss0:mov al, 'a'jmp ssend:mov ax, 0 ;将原int9中断的IP,CS恢复mov ds, axmov ax, datamov es, axpush es:[0]pop ds:[9*4]push es:[2]pop ds:[9*4 + 2]mov ax, 4C00Hint 21Hdo9h:push axpush dxpush dsin al, 60H ;从键盘端口读出键盘的输入mov dl, alpushf ;模仿int指令,进行原int9的调用pushf ;将标致寄存器的IF和TF置零pop axand ah, 11111100Bpush axpopfmov ax, data;保存下一条指令的IP和CSmov ds, axcall dword ptr ds:[0]cmp dl, 1 ;ESC的扫描码为1jne okjmp send ;跳到循环外,不再执行循环指令ok:pop dspop dxpop axiretdelay:push dxpush axmov dx, 10Hmov ax, 0s1:sub ax, 1 ;-1的反码是65535sbb dx, 0 ;此时CF寄存器是1,则dx-1cmp ax, 0 ;内循环jne s1cmp dx, 0 ;外循环 jne s1pop axpop dxretcode endsend start
运行结果:
按下ESC键后的显示结果:
为了避免在修改int 9的IP和CS时就发生外部中断,那么会让中断的地址混乱,所以可以改进一下程序
指令:cli:设置IF=0,屏蔽中断
sti:设置IF=1,不屏蔽中断
将这两条指令分别加在修改入口地址的前后,那么就可以避免上面说的那种情况了
例:
cli ;设置IF=0,屏蔽中断mov ax, 0 ;将新的int9中断的IP,CS写入中断向量表中mov ds, axmov word ptr ds:[9*4], offset do9hmov word ptr ds:[9*4 + 2], cssti ;设置IF=1,不屏蔽中断
这样就避免了在修改IP,CS时发生外部中断
这里还有个问题,这里的jmp是有范围的,如果在程序中超出了jmp的范围,那么就不能完美的跳出程序了,为了解决这个问题,还需要模拟利用中断模拟jmp指令,让jmp指令的范围得到扩充
因为进入到外部中断时,会将CS和IP入栈,只要改变一下IP,在跳回程序后,就能跳到指定的位置
在中断中:
mov bp, sp ;模拟jmp指令,跳出循环mov word ptr [bp + 8], offset send
这样就能跳出循环了
完整的代码:
assume cs:codedata segment ;储存原int9的IP和CSdw 0, 0data endscode segmentstart:mov ax, 0 ;将原int9的IP和CS放到data空间中mov ds, axmov ax, datamov es, axpush ds:[9*4]pop es:[0]push ds:[9*4 + 2]pop es:[2]mov ax, 0 ;将新的int9中断的IP,CS写入中断向量表中mov ds, axmov word ptr ds:[9*4], offset do9hmov word ptr ds:[9*4 + 2], csmov ax, 0B800Hmov ds, axmov al, 'a'mov cl, 2s:mov ds:[10*160 + 8*2], almov byte ptr ds:[10*160 + 8*2 + 1], clcall delay ;调用延时的子程序,方便显示cmp al, 'z'je s0inc aljmp ss0:mov al, 'a'jmp ssend:mov ax, 0 ;将原int9中断的IP,CS恢复mov ds, axmov ax, datamov es, axpush es:[0]pop ds:[9*4]push es:[2]pop ds:[9*4 + 2]mov ax, 4C00Hint 21Hdo9h:push axpush dxpush dsin al, 60H ;从键盘端口读出键盘的输入mov dl, alpushf ;模仿int指令,进行原int9的调用pushf ;将标致寄存器的IF和TF置零pop axand ah, 11111100Bpush axpopfmov ax, data;保存下一条指令的IP和CSmov ds, axcall dword ptr ds:[0]cmp dl, 1 ;ESC的扫描码为1jne okmov bp, sp ;模拟jmp指令,跳出循环mov word ptr [bp + 6], offset sendok:pop dspop dxpop axiretdelay:push dxpush axmov dx, 10Hmov ax, 0s1:sub ax, 1 ;-1的反码是65535sbb dx, 0 ;此时CF寄存器是1,则dx-1cmp ax, 0 ;内循环jne s1cmp dx, 0 ;外循环 jne s1pop axpop dxretcode endsend start
效果是一样的
- 汇编语言中的外中断——键盘事件
- 汇编语言 — 中断
- 读王爽老师汇编语言笔记---int指令、端口、外中断以及键盘的输入
- 汇编语言-端口和外中断
- babyos (十二) —— 键盘中断
- Qt中的键盘事件
- java中的键盘事件
- Qt中的键盘事件
- Qt中的键盘事件
- Qt中的键盘事件
- js中的键盘事件
- Qt中的键盘事件
- Vue2中的键盘事件
- Qt中的键盘事件
- Vue2中的键盘事件
- Vue2中的键盘事件
- 汇编语言中断程序实例——定时小程序
- 王爽《汇编语言》实验13——编写、应用中断例程
- 隐试意图激活另外一个Activity
- 字符编码总结:ASCII,Unicode和UTF-8
- 线段树:【bzoj3772】
- Java学习记录(记录一部分Java和C++区别和Java里一些比较重要的概念)--稍后会转到新浪博客
- NIO之Buffer的clear()、rewind()、flip()方法的区别
- 汇编语言中的外中断——键盘事件
- CodeForces 151 B 结构体排序。
- (hdu step 1.3.4)百步穿杨
- android:程序无响应,你该如何定位问题?
- Java_集合操作_合并两个map
- HtmlAgilityPack 总结(一)
- Android模拟器快捷键
- 粥做得好不好,全凭一个良心!
- Libevent源码分析-----TAILQ_QUEUE队列