-
接口芯片和端口
外设通过接口芯片的端口和CPU交流
CPU在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设输入。
外中断信息
外中断类型
- 可屏蔽中断
- 不可屏蔽中断
- CPU是否响应可屏蔽中断看标志寄存器IF位的设置
- IF=0,不响应可屏蔽中断
- IF=1,CPU在执行完当前指令后响应中断,引发中断过程
- 可屏蔽中断信息来自于CPU外部,中断类型码通过数据总线送入CPU(和内中断区别:不是CPU产生的)
- 其他和内中断设置相同
- 初始IF=0
- 设置IF=1:sti
- 设置IF=0:cli
- 不可屏蔽中断
- 执行完当前指令后立即响应
- 对于8086CPU,不可屏蔽中断的中断类型码位2,所以中断过程不需要取中断类型码
-
键盘处理过程
键盘输入->引发9号中断->执行int 9中断例程
- 按下和松开按键时的扫描码都被送入60H端口中
- 按下键产生的扫描码:通码,1个字节,第7位为0
- 松开键产生的扫描码:断码,1个字节,第7位为1
- 断码=通码+80H
- 工作过程
- 1)读出60h端口中的扫描码
- 2)如果是字符键的扫描码,将该扫描码和它对应的字符码(ASCII/UNICODE)送入内存中的BIOS键盘缓冲区;
- 3)相关芯片向CPU发出中断类型码为9的可屏蔽中断信息
- 4)CPU检测到中断信息后,如果IF=1,响应中断,转去执行int 9中断例程,IF置0,执行完后再IF置0
- 5)如果是控制键,将其转变为状态字节,写入内存中存储状态字节的单元,输入输出时会检查这里的值;
- BIOS键盘缓冲区:BIOS用于存放int 9中断例程所接收的键盘输入的内存区。
- 可以存储15个键盘输入
- 一个键盘输入用一个字单元存放:高位字节存放扫描码,低位字节存放字符码
- 0040:17单元存储键盘状态字节,按位标志相关控制键和切换键的状态
模拟修改int9例程(依次显示a~z)
assume cs:codestack segmentdb 128 dup(0)stack endsdata segemntdw 0,0data endscode segmentstart: mov ax,stackmov ss,axmov sp,128 ;!!mov ax,datamov ds,axmov ax,0mov es,axpush es:[9*4]pop ds:[0]push es:[9*4+2]pop ds:[2] ;将原来int 9中断例程的入口地址保存在ds:0和ds:2单元中mov word ptr es:[9*4],offset int9mov es:[9*4+2],cs ;在中断向量表中设置新的int9的入口地址mov ax,0b800hmov es,axmov ah,'a's: mov es:[160*12+40*2],ahinc ahcmp ah,'z'call delay ;(time.sleep())jna smov ax,0mov es,axpush ds:[0]pop es:[9*4]push ds:[1]pop es:[9*4+2];原本的中断例程恢复mov ax,4c00hint 21hdelay:push axpush dxmov dx,1000h;循环10000000次mov ah,0s1:sub ax,1sbb dx,0cmp ax,0jne s1cmp dx,0jne s1pop dxpop axretint9:push axpush bxpush esin al,60h;获得键盘扫描码pushf ;保留int9模拟程序中的各个标志位;模拟flag的IF和TF位在执行int中断例程时置零pushf ;模拟原始int中断的标志寄存器进栈pop bx ;栈里的flagand bh,11111100b ;TF IF标志位置0push bx ;修改后的flag入栈popf ;覆盖flagcall dword ptr ds:[0];上面执行完个性化后,调用原来的int 9中断例程cmp al,1;键盘扫描码为1,改变颜色jne int9retmov ax,0b800h ;显存段地址mov es,axinc byte ptr es:[160*12+40*2+1];属性增加1,改变颜色int9ret:pop es,pop bxpop axiret ;中断返回code endsend start
安装新的int 9中断例程(按F1键改变屏幕显示颜色,DOS实模式下才能成功)
;1)改变颜色mov ax,0b800hmov es,axmov bx,1mov cx,2000 ;整个显存的所有字节s:inc byte ptr es:[bx]add bx,2loop s;2)保存原int 9的入口地址;3)安装新int 9的入口地址
指令系统总结
- 数据传送指令
- mov\push\pop\pushf\popf
- xchg:两个寄存器,寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同,可以是一个字节,也可以是一个字,也可以是双字。
- 算术运算指令(影响sf、zf、of、cf、pf、af位)
- add\sub\adc\sbb\inc\dec\cmp\imul\idiv\aaa
- imul:将被乘数与乘数均作为有符号数, 它按照符号扩展方式扩展到目标操作数格式的长度
- 逻辑指令(除了not指令外,其他都会影响flag相关标志位)
- and\or\not\xor\test\shl\shr\sal\sar\rol\ror\rcl\rcr
- 转移指令(可以修改CS和IP或单一修改IP)
- jmp\jcx\je\jb\ja\jnb\jna\loop\call\ret\retf\int\iret
- 处理机控制指令
- cld\std\sli\sti\nop\clc\cmc\stc\hlt\wait\esc\lock
- 串处理指令
- movsb\movsw\cmps\scas\lods\stos
