From: AceVest Date: Sat, 30 Oct 2021 03:14:59 +0000 (+0800) Subject: add keyboard_interrupt.asm X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=20aa94e26c6201188718a631b2b1dd2f6afa64c4;p=acecode.git add keyboard_interrupt.asm --- diff --git a/learn/keyboard_interrupt.asm b/learn/keyboard_interrupt.asm new file mode 100644 index 0000000..a5ef7a3 --- /dev/null +++ b/learn/keyboard_interrupt.asm @@ -0,0 +1,136 @@ + +; ------------------------------------------------------------------------ +; File Name: keyboard_interrupt.asm +; Author: Zhao Yanbai +; 2021-10-29 23:20:37 Friday CST +; Description: +; 初始化8259将其中断向量号设置为0x20 +; 中断EOI方式设置为手动EOI +; 并禁用所有中断,只开启键盘中断 +; 每收到一次键盘中断,就将屏幕上显示的字符变化一下 +; ------------------------------------------------------------------------ + + +BITS 16 +ORG 0x7C00 +IntVect EQU 0x20 +_start: + jmp 0x0000:entry +entry: + mov ax, cs + mov ds, ax + mov ss, ax + mov sp, 0x7C00 + + ; 调用BIOS清屏,并设置为80x25的彩色文本模式 + ; 功能号: 0x00 + ; 用途: 设置显示模式 + ; 参数: AL = 显示模式号 + ; AL=0x00: 40x25黑白文本 + ; AL=0x01: 40x25彩色文本 + ; AL=0x02: 80x25黑白文本 + ; AL=0x03: 80x25彩色文本 + ; ... + mov ah, 0x00 + mov al, 0x03 + int 0x10 + + ; 将es设为显存段地址 + mov ax, 0xB800 + mov es, ax + + ; 在中断向量表中设置键盘中断程序入口地址 + mov bx, (IntVect+1)*4 + mov ax, ds + mov cx, kbd_isr + mov [bx + 0x00], cx + mov [bx + 0x02], ax + + ; 准备初始化8259 + cli + + ; 先初始化主片 + ; ICW1: 需要ICW4,级连状态 + mov al, 0001_0001b + out 0x20, al + + ; ICW2: 中断向量地址为0x20 + mov al, IntVect + out 0x21, al + + ; ICW3: 主片2号IR输入引脚连着从片 + mov al, 0000_0100b + out 0x21, al + + ; ICW4: 非缓冲,手动发送EOI的80x86模式 + mov al, 0000_0001b + out 0x21, al + + ; 再初始化从片 + ; ICW1: 需要ICW4,级连状态 + mov al, 0001_0001b + out 0xA0, al + + ; ICW2: 中断向量地址为0x28 + mov al, IntVect+0x08 + out 0xA1, al + + ; ICW3: 从片连在主片的2号IR输入引脚 + mov al, 0000_0010b + out 0xA1, al + + ; ICW4: 非缓冲,手动发送EOI的80x86模式 + mov al, 0000_0001b + out 0xA1, al + + ; 主片OCW1: 解除主片上键盘的中断屏蔽 + mov al, 1111_1101b + out 0x21, al + + ; 从片OCW1: 屏蔽从片上的所有中断 + mov al, 1111_1111b + out 0xA1, al + + ; 打开CPU中断允许标志 + sti + +run: + hlt + jmp run + +kbd_isr: + push ax + push bx + + ; 从键盘缓冲区中读取输入 + in al, 0x60 + test al, 0x80 + jnz .ignore ; 如果是break code就跳过 + + ; 变化显示字符 + mov bl, [cnt] + cmp bl, 26 + jbe .letter + mov bl, 0 + .letter: + mov al, bl + add al, 'A' + inc bl + mov [cnt], bl + + mov byte [es:0], al + mov byte [es:1], 0x0C + + .ignore: + ; 给主片发送EOI + ; OCW2 + mov al, 0110_0001b + out 0x20, al + + pop bx + pop ax + iret + + cnt db 0 + times 510 - ($ - $$) db 0 + dw 0xAA55