§ Объяснение
Очень часто, когда переводится программа в защищенный режим, возникает проблема с IRQ, которые по старинке, находятся по адресам 08-0F для Master и 70-77 для Slave, что совершенно неприемлемо, потому что на векторах 00-1F зарезервированы системные
исключения, которые надо тоже как-то обрабатывать. Из-за этого, надо сделать код, который перенаправляет на новые вектора 20-2F. Этот код ниже.
§ Вектора системных исключений
; Offset | INT # | Description
; -----------+-----------+-----------------------------------
; $0000 | 0x00 | Divide by 0
; $0004 | 0x01 | Trace
; $0008 | 0x02 | NMI Interrupt
; $000C | 0x03 | Breakpoint (INT3)
; $0010 | 0x04 | Overflow (INTO)
; $0014 | 0x05 | Bounds range exceeded (BOUND)
; $0018 | 0x06 | Invalid opcode (UD2)
; $001C | 0x07 | Device not available (WAIT/FWAIT)
; -----------------------------------------------------------
; $0020 | 0x08 | Double fault
; $0024 | 0x09 | Coprocessor segment overrun
; $0028 | 0x0A | Invalid TSS
; $002C | 0x0B | Segment not present
; $0030 | 0x0C | Stack-segment fault
; $0034 | 0x0D | General protection fault
; $0038 | 0x0E | Page fault
; $003C | 0x0F | ---
; $0040 | 0x10 | x87 FPU error
; $0044 | 0x11 | Alignment check
; $0048 | 0x12 | Machine check
; $004C | 0x13 | SIMD Floating-Point Exception
; $00xx | 0x14-0x1F | ---
; -----------------------------------------------------------
§ Код
На всякий случай, если включен APIC — более расширенная версия PIC, нужно его отключить в целях совместимости со старым железом, таким как 386 и ниже.
1push ax
2mov ecx, 1Bh
3rdmsr
4and eax, 0xFFFFF7FF
5wrmsr
Помимо редиректа, на вход подается AX, 16 бит которые обозначают, разрешены ли прерывания IRQ или нет. Например если установлен бит 0, то разрешен IRQ#0 (Timer).
1mov al, 0x10 + 0x01
2out 0x20, al
3out 0xA0, al
4mov al, 0x20
5out 0x21 , al
6mov al, 0x28
7out 0xA1, al
8mov al, 4
9out 0x21, al
10mov al, 2
11out 0xA1, al
12mov al, 0x01
13out 0x21, al
14out 0xA1, al
15pop bx
16not bx
17mov al, bl
18out 0x21, al
19mov al, bh
20out 0xA1, al
21ret