PIC
可编程中断控制器(PIC - Programmable Interrupt Controller)是微机系统中管理设备中断请求的管理者。当PIC向处理器的INT引脚发出一个中断信号时,处理器会立刻停下当时所做的事情并询问PIC需要执行哪个中断服务请求。PIC则通过向数据总线发出与中断请求对应的中断号来告知处理器要执行哪个中断服务过程。处理器则根据读取的中断号通过查询中断向量表(在32位保护模式下是中断描述符表)取得相关设备的中断向量(即中断服务程序的地址)并开始执行中断服务程序。当中断服务程序执行结束,处理器就继续执行被中断信号打断的程序。
INT.H
#ifndef __INT_H__
#define __INT_H__
void init_pic(void);
//IMR是中断屏蔽寄存器 8位分别对应8路IRQ信号 哪一位位1则屏蔽哪一路
//ICW是初始化控制数据
//ICW1和ICW4与PIC主板配线方式有关
//ICW3是有关主从连接的设定 决定几号IRQ和从PIC相连 在我们的电脑中是2号
//ICW2决定IRQ以哪一号中断通知CPU
#define PIC0_ICW1 0x0020
#define PIC0_OCW2 0x0020
#define PIC0_IMR 0x0021
#define PIC0_ICW2 0x0021
#define PIC0_ICW3 0x0021
#define PIC0_ICW4 0x0021
#define PIC1_ICW1 0x00a0
#define PIC1_OCW2 0x00a0
#define PIC1_IMR 0x00a1
#define PIC1_ICW2 0x00a1
#define PIC1_ICW3 0x00a1
#define PIC1_ICW4 0x00a1
#endif
INT.C
//主PIC上 有IRQ 0-7
//从PIC 有IRQ 8-15
//从PIC连接在主PIC的IRQ2上
void init_pic(void)
{
io_out8(PIC0_IMR, 0xff); //禁用所有中断
io_out8(PIC1_IMR, 0xff); //禁用所有中断
io_out8(PIC0_ICW1, 0x11); //设置边沿触发模式
io_out8(PIC0_ICW2, 0x20); //IRQ0-7 由INT 20-27接收
io_out8(PIC0_ICW3, 1 << 2);//PIC0 由IRQ2 连接
io_out8(PIC0_ICW4, 0x01); //无缓冲区模式
io_out8(PIC1_ICW1, 0x11); //设置边沿触发模式
io_out8(PIC1_ICW2, 0x28); //IRQ8-15 由INT 28-2f接收
io_out8(PIC1_ICW3, 2);//PIC0 由IRQ2 连接
io_out8(PIC1_ICW4, 0x01); //无缓冲区模式
io_out8(PIC0_IMR, 0xfb); //PIC1以外全部禁止
io_out8(PIC1_IMR, 0xff); //禁用所有中断
return;
}
中断发生以后
当中断发生以后,如果CPU可以受理这个中断,CPU会命令PIC发送两个字节的数据
0XCD 0X??
这送过来的两字节的数据,CPU会把它当做命令执行
0XCD 代表调用BIOS时的那个INT指令
??代表什么呢?
代表当时的那个中断号
我们在程序里写的INT 0X10 便会被翻译成
0XCD 0X10
三个中断处理函数
//键盘
void IntHandler21(int *pEsp)
{
struct BOOTINFO *pBootIf = (struct BOOTINFO *)ADR_BOOTINFO;
DrawBoxFillColor8(pBootIf->pVram, pBootIf->sScrnx, COL8_BigRed,
0, 0, 32 * 8 - 1, 15);
OutPutString8_ASCII(pBootIf->pVram, pBootIf->sScrnx,
0, 0, COL8_BigGreen, "INT 21 (IRQ-1) : PS/2 keyboard");
for (;;) {
io_hlt();
}
}
//鼠标
void IntHandler2C(int *pEsp)
{
struct BOOTINFO *pBootIf = (struct BOOTINFO *)ADR_BOOTINFO;
DrawBoxFillColor8(pBootIf->pVram, pBootIf->sScrnx, COL8_BigRed,
0, 0, 32 * 8 - 1, 15);
OutPutString8_ASCII(pBootIf->pVram, pBootIf->sScrnx,
0, 0, COL8_BigGreen, "INT 2C (IRQ-12) : PS/2 mouse");
for (;;) {
io_hlt();
}
}
//PIC
void IntHandler27(int *pEsp)
{
io_out8(PIC0_OCW2, 0x67);
return;
}
调用中断处理函数
_asm_IntHandler21:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL _IntHandler21
POP EAX
POPAD
POP DS
POP ES
IRETD
_asm_IntHandler27:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL _IntHandler27
POP EAX
POPAD
POP DS
POP ES
IRETD
_asm_IntHandler2C:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL _IntHandler2C
POP EAX
POPAD
POP DS
POP ES
IRETD