-
接口芯片和端口
外设通过接口芯片的端口和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:code
stack segment
db 128 dup(0)
stack ends
data segemnt
dw 0,0
data ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,128 ;!!
mov ax,data
mov ds,ax
mov ax,0
mov es,ax
push 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 int9
mov es:[9*4+2],cs ;在中断向量表中设置新的int9的入口地址
mov ax,0b800h
mov es,ax
mov ah,'a'
s: mov es:[160*12+40*2],ah
inc ah
cmp ah,'z'
call delay ;(time.sleep())
jna s
mov ax,0
mov es,ax
push ds:[0]
pop es:[9*4]
push ds:[1]
pop es:[9*4+2];原本的中断例程恢复
mov ax,4c00h
int 21h
delay:push ax
push dx
mov dx,1000h;循环10000000次
mov ah,0
s1:sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
int9:push ax
push bx
push es
in al,60h;获得键盘扫描码
pushf ;保留int9模拟程序中的各个标志位
;模拟flag的IF和TF位在执行int中断例程时置零
pushf ;模拟原始int中断的标志寄存器进栈
pop bx ;栈里的flag
and bh,11111100b ;TF IF标志位置0
push bx ;修改后的flag入栈
popf ;覆盖flag
call dword ptr ds:[0];上面执行完个性化后,调用原来的int 9中断例程
cmp al,1;键盘扫描码为1,改变颜色
jne int9ret
mov ax,0b800h ;显存段地址
mov es,ax
inc byte ptr es:[160*12+40*2+1];属性增加1,改变颜色
int9ret:
pop es,
pop bx
pop ax
iret ;中断返回
code ends
end start
安装新的int 9中断例程(按F1键改变屏幕显示颜色,DOS实模式下才能成功)
;1)改变颜色
mov ax,0b800h
mov es,ax
mov bx,1
mov cx,2000 ;整个显存的所有字节
s:inc byte ptr es:[bx]
add bx,2
loop 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