实模式下,中断向量大小4字节,低两个字节是中断向量的偏移地址即IP,高两节保存的是中断向量的段地址即 CS。中断向量表位于内存地址 0x0 处, 包含 256个中断向量, 表的大小为 256*4 = 1024(Byte) 即 1K。系统默认中断号和地址对应关系如下:8259A主片
中断号 接入引脚 中断源 地址
0x8+0 ir0 8253 时钟 0x20 ~ 0X23
0x8+1 ir1 8255 键盘 0x24 ~ 0X27
0x8+2 ir2 * 0x28 ~ 0X2B
0x8+3 ir3 * 0x2C ~ 0X2F
0x8+4 ir4 * 0x30 ~ 0x33
0x8+5 ir5 * 0x34 ~ 0x37
0x8+6 ir6 * 0x38 ~ 0x3b
0x8+7 ir7 * 0x3C ~ 0x3f
中断号 = 中断类型 + 引脚的标号
地址 = 中断号 * 4
在ICW2中初始化 只需要设置 中断类型号就行了。
一、实模式下BIOS默认的键盘中断
示例:
seg_7c00 = 0x07c0
entry start
;;; BIOS 自动将引导扇区 装载进内存 0x7c00,并开始执行引导程序
start:
jmpi init_seg, #seg_7c00
;;; 初始化段
init_seg:
mov ax, cs
mov ds, ax
mov ss, ax
mov es, ax
mov sp, #1024
;;; 程序
die:
mov ah, #0x0 ;; 0x16中断 0号功能 阻塞等待 键盘缓冲区,有字符就 放进al,没有字符就阻塞
int 0x16
mov ah, #0x0e ;; 0x10号中断 0x0e功能号屏幕输出一个字符,光标随之移动
mov bx, #0x01
int 0x10
jmp die
.org 510
.word 0xAA55 ;;; 引导标志
二、替换BIOS键盘中断向量,按下按键在屏幕输出字符 ‘A’
1.代码
seg_7c00 = 0x07c0
entry start
start:
jmpi init_seg, #seg_7c00
init_seg:
mov ax, cs
mov ds, ax
mov ss, ax
mov es, ax
mov sp, #1024
cli
call setup_intr ;; 修改 09号中断的向量地址
call init_8259 ;; 初始化 8259
sti
die: jmp die
init_8259:
;;;;; ICW1
mov al, #0x11 ; 0001 0001 级联,边沿触发,要ICW4
out 0x20, al ; 主ICW1
out 0xA0, al ; 从ICW1
;;;;; ICW2
mov al, #0x08 ; 中断类型号0x08
out 0x21, al ; 主ICW2
mov al, #0x30 ; 中断类型号0x30
out 0xA1, al ; 从ICW2
;;;;; ICW3
mov al, #0x04 ; 主片 IR2号 引脚 接入从片 INT
out 0x21, al ; 主ICW3
mov al, #0x02 ; 从片 INT 连接到主片 ir2
out 0xA1, al ; 从ICW3
;;;;; ICW4
mov al, #0x1 ; 8086 非缓冲方式 , 手工 EOI
out 0x21, al ; 主ICW4
out 0xA1, al ; 从ICW4
;;;;; OCW1
mov al, #0xfd ; 主 OCW1 = 1111 1101 允许IR1中断请求 键盘
out 0x21, al
mov al, #0xff ; OCW1= 1111 1111
out 0xA1, al ; 从 OCW1
ret
setup_intr:
push ds
mov ax, #0x0
mov ds, ax
mov ax, #intr09 ;; 偏移地址 ip
mov [0x0024], ax ;;
mov ax, cs
mov [0x0026], ax ;;; cs
pop ds
ret
;;;;; 一般的键盘输入,在CPU执行完int 9中断例程后,ASCII都放到了键盘缓冲区中
;;;;; 大小可以存储 15个 按键扫描码和ASCII码
intr09:
push ax
push bx
in al, 0x60 ; 通过8255A的PA口(PA口地址为0x60)读取键盘扫描码
mov ah, al
in al, 0x61 ; 读0x61口 bits[7] 先置 1(禁止) 在 清零(恢复)
or al, #0x80 ; 先禁止键盘,在马上恢复键盘,用于对收到的扫描码做出应答
out 0x61, al
jmp 1f
1: jmp 1f
1: and al, #0x7F
out 0x61, al ; 复位 PPI pb7 使键盘回复工作
test ah, #0x80 ; 相等 键被释放 break=mark+0x80
jne rto ; 不相等,结束
call display_key ; 显示字符
rto:
mov al, #0x20 ;; OCW2
out 0x20, al ;; 给8259发送 EOI , 中断结束 ISR 对应位置 reset
pop bx
pop ax
iret
display_key:
push cx
push bx
push ax
push dx
sti
mov cx, #0x1
n:
mov ah, #0x0e ; 显示字符(光标前移)
mov al, #65 ; 打印字符A
mov bx, #0x01 ;
int 0x10
call deley
loop n
pop dx
pop ax
pop bx
pop cx
ret
deley:
push cx
mov cx, #0xf00
d0: push ax
pop ax
loop d0
pop cx
ret
.org 510
.word 0xAA55
编译:
as86 -0 -a -o kboard.o kboard.s
ld86 -0 -s -o kboardkboard.o
dd if=kboard of=kboard.img bs=32 skip=1