Chinaunix首页 | 论坛 | 博客
  • 博客访问: 497318
  • 博文数量: 161
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1947
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-25 01:20
文章分类

全部博文(161)

文章存档

2011年(44)

2010年(47)

2009年(48)

2008年(22)

我的朋友

分类:

2009-08-29 04:49:24

外中断
cpu对指令的执行+对外部设备的控制(i/o)
要即时处理外设的输入,要解决两个问题
外设的输入随时可能发生
cpu如何得知?
从何处得知外设的输入?

1>接口芯片和端口
外设的输入不是直接送入内存和cpu,
先送入接口芯片的端口中(对cpu来说芯片的端口,就是对芯片来说,芯片的寄存器)
再由相关的芯片送到外设
cpu可通过端口和外设进行联系
2>
外部中断
来自cpu外部
例如:外设的输入到达时,相关芯片向cpu发出相应的中断信息,cpu在执行当前指令的时候,可以检测到发送过来的中断信息,引发中断过程没,
去处理外设的输入
pc系统中,外中断共两类
可屏蔽中断(cpu可以不响应,是否响应,看标志寄存器if)
if=1 去响应,在中断处理程序中,需要处理可屏蔽中断  sti
if=0 不响应                                      cli
中断过程
1取得中断类型码
2标志寄存器push  ;if=0 tf=0
3push cs ip
4更改ip cs(该中段在中断向量的入口地址)
5转去处理中断处理程序
与内中断的区别
第一步实现不同,别的基本一样
原因:内中断的中断类型取得来自cpu内部产生  
     外中断的中断类型取得依靠数据总线送人cpu

不可屏蔽中断
cpu必须响应
中断类型码固定:2
中断过程中不需要取得中断类型码
1标志寄存器push  ;if=0 tf=0
2push cs ip
3(ip)=(8) (cs)=(0ah)(该中段在中断向量的入口地址)
转去处理中断处理程序

总结:
几乎所有外设引发的外中断,都是可屏蔽中断
不可屏蔽中断是系统中有必须处理的紧急情况发生时
用来通知cpu的中断信息
 

3>具体例子
pc机键盘的处理过程
体会pc机处理外设的基本放入
键盘上有一个芯片
键盘输入
1
按键
按下一个键时,开关接通,该芯片就产生一个扫描码,扫描码说明按下了的键在键盘上的位置
扫描码被送入主板的相关寄存器芯片的寄存器中,该寄存器的端口地址为60h
按下键->键盘上芯片产生扫描码(通码,长度1B,第7位是0)->将该码送入主板接口上的寄存器上60h
->到达60h端口后,相关芯片就会向cpu发出中断类型为9的可屏蔽中断信息->cpu检测到该中断信息后,if=1,响应中断,引发中断过程,转去执行int9 中断例程
2松键
松开键->键盘上芯片产生扫描码(断码,长度1B,第7位是1)->将该码送入主板接口上的寄存器上60h->
断码=通码+80

4>
执行int 9中断例程
bios提供int 9的中断处理程序
主要工作:
1:读取60端口的扫描码
2:如果是字符键。将该扫描码和对应的字符码ascii送入内存中的bios键盘缓冲区
   如果是控制键和切换键,将其转换为状态字节写入内存中存储状态字节的单元
3:对键盘系统进行相关的控制,例如向相关芯片发出应答信息
bios键盘缓冲区:系统启动后,bios用于存放int 9 中断例程
所接收的键盘输入的内存区,该内存存储15个键盘输入,一个键盘输入用一个字单元存放
高字节:扫描码
第字节:字符码
0040:17单元存放键盘状态字节,记录控制键和切换键的状态
8位分别是
0  略
1
2
3
4
5
6
7

5>
编写int 9中断例程
完整的编写一个键盘中断的处理程序,要涉及到一些硬件细节
硬件细节的处理:bios提供的int 9中断历程已经对这些硬件细节进行了处理
我们只要在自己编写的中断例程中调用bios的int9中断例程就可以了
///////////////////////////////////////////////////////////////////////////////////////
依次显示a-z
assume cs:code
code segment
start: 
 mov ax,0b800h
 mov es,ax      ;设置es
 mov ah,'a'
s: mov es:[160*12+40*2],ah
 inc ah
 cmp ah,'z'
 jna s         ;ah没有比z大就jmp
 mov ax, 4c00h
 int 21h
 
code ends
end start
///////////////////////////////////////////////////////////////////////////////////////
delay,cpu延迟代码
mov dx,10h
mov ax,0
s:
sub ax,1
sbb dx,0
cmp ax,0
jne s
cmp dx,0
jne s
///////////////////////////////////////////////////////////////////////////////////////
cpu转去执行int 9中断例程
(新的自己写的中断程序)cpu转去执行int 9中断例程:以下是已经在自己写的int 9断程序中
从60h端口读出键盘的输入  in al,60h
调用bios的int 9中断例程,处理其他硬件细节(在中断程序中在调用int 9编号为n的bios中断程序,处理硬件细节,不能用int指令来调用)
判断是否是esc键的扫描码
                 如果是,改变颜色,返回
                 如果不是,直接返回
问题:
我们写的中断处理程序是新的int 9中断程序,主程序必须要将中断向量入口地址指向我们自己写的中断处理程序
要能我们写的新中断例程调用原理的中断例程,就必须在int 9的中断向量的cs:ip改写之前保持原理的cs:ip
 

///////////////////////////////////////////////////////////////////////////////////////
编写模拟int程序
 
在自己写的程序中要调用原来int 9,由于事先保持原理的int 9中断处理程序的入口地址ds:0 ds:2
不能用int 所以自己写程序模拟int 指令的过程:
取得中断类型码    ;这个只是为了得到int 9中断向量的入口地址,可以省去,cs:ip已知
1:push flag寄存器
2:if=0 tf=0
3:push cs ip
4:(ip)=(n*4) (cs)=(n*4+2)   n=(ds)
int的模拟步骤
用栈保存原来的寄存器
1:push flag  用pushf,保存原来的flag
2:if=0 tf=0     ;注意:在该中断程序中用
2:call dword ptr ds:[0]
具体代码:
pushf  ;标志寄存器push
pushf
pop bx
and ah,11111100b
push bx
popf                ;if=0.ft=0
call dword ptr ds:[0]    ;跳到原来int 9中断处理程序入口
 
///////////////////////////////////////////////////////////////////////////////////////
如果是esc键的扫描码,改变显示的颜色后返回
显示位置:
屏幕中间,第12行40列,
偏移地址160*12+40*2
字符送入b800:160*12+40*2,b800:160*12+40*2+1是字符属性

完整的代码:
assume cs:code
stack segment
db 128 dup (0)
stack ends
data segment
dw 0,0
data segment
code segment
start:
 mov ax,stack
 mov ss,ax
 mov sp,128   ;设置栈顶指针

 mov ax,data
 mov ds,ax    ;设置ds断地址data
 mov ax,0
 mov es,ax    ;设置es=0,为获得原理的int 9中断程序的入口地址
 push es:[9*4]
        pop ds:[0]
 push es:[9*4+2]
 pop ds:[2]   ;将原来的int 9中断例程的入口地址保存

        mov word ptr es[9*4] ,offset int9
        mov es:[9*4+2],cs      ;在中断向量表中设置新的in9中断处理程序的入口地址
 mov ax,0b800h
        mov es,ax
 mov ah,'a'             ;es段寄存器用于定位显存
s: mov es:[160*12+40*2],ah
 call delay
 inc ah
 cmp ah,'z'
 jna s         ;ah没有比z大就jmp
 mov ax, 0
 mov es,ax
 push ds:[0]
 pop es:[9*4]
 push ds:[2]
 pop es:[9*4+2]
 mov ax,4c00h
 int 21h
delay:
 ;
 ;
 ;
 ;
;----------------INT 9中断例程
int9:
 push ax
 push bx
 push es
;//////////////////////////////////step1
 in al,60h
;////////////////////////////////////模拟int
 pushf  ;标志寄存器push
 pushf
 pop bx
 and ah,11111100b
 push bx
 popf                ;if=0.ft=0
 
;//////////////////////////////////////////
 call dword ptr ds:[0]
 
 cmp al,l
 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
原理图:
改变中断向量的int9 中断入口地址
|
|
|
显示字符(call delay)
|
|
|
恢复中断向量
|
|
|
int 21
——————————
int 中断程序
用栈保存原来的寄存器
读入端口数据
模拟中断
1:push flag  用pushf,保存原来的flag
2:if=0 tf=0     ;注意:在该中断程序中用
3:call dword ptr ds:[0]
4:处理原来中断 ,处理硬件细节

继续执行当前
cmp al,1 ;检测是否是esc,不是,goto不是
是:
{改变显示颜色}
不是:
{pop
  iret (pop cs ip)
 }
 
 
指令系统总结
数据传送指令
mov push pop pushf popf xchg
算术运算指令
add sub abc sbb inc dec cmp imul idiv
aaa

逻辑指令
and or nor kxor test shl shr sal rol ror rcl rcr

转移指令
修改ip或同时修改ip和cs
无条件jmp
有条件jcxz je jb ja jnb jna
循环:loop
过程:call ret retf
中断:int iret

处理机控制指令
cld std cli stl nop clc cmc stc hlt wait esc lock
串处理指令
内存中批量数据进行操作
movsb movsw cmps scas lods stos
 
 
 

 
 
 
 
 
 
 
 

 
 

 
阅读(668) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-06-05 02:17:19

大连法律咨询在线 http://www.fabowang.com 大连律师在线咨询 http://www.fabowang.com 大连法律顾问网 http://www.fabowang.com 大连律师咨询 http://www.fabowang.com