Настройка прерываний в защищенном режиме (x86)

Как происходит настройка прерываний в защищенном режиме?

это ссылка говорит, что нужно:

Освободить место для таблицы дескрипторов прерыванийСообщите процессору, где находится это пространство (см. Учебное пособие по GDT: lidt работает так же, как lgdt)Скажите PIC, что вы больше не хотите использовать настройки BIOS по умолчанию (см. Программирование микросхем PIC)Напишите пару обработчиков ISR (см. Подпрограммы обработки прерываний) для IRQ и исключенийПоместите адреса обработчиков ISR в соответствующие дескрипторыВключить все поддерживаемые прерывания в маске IRQ (PIC)

Третий шаг не имеет смысла для меня (я посмотрел наэтот ссылка, но ничего не было сказано о PIC), поэтому я проигнорировал это и выполнил следующие два шага, только чтобы снова оказаться в неведении, когда я достиг последнего шага. Однако, исходя из моего понимания прерываний, оба шага, которые я не понимал, относятся к аппаратным прерываниям от контроллера PIC и не должны влиять на прерывания, вызванные PIT на IRQ 0. Поэтому я также проигнорировал этот шаг.

Когда я запускал свой код, он прекрасно компилировался и даже работал на виртуальной машине, но прерывание, казалось, срабатывало только один раз. Затем я понял, что не посылаю EOI в PIC, не позволяя ему вызывать больше прерываний. Тем не менее, добавивmov al, 0x20 а такжеout 0x20, al как раз передiret инструкция вызывает сбой виртуальной машины.

Вот моя IDT:

; idt
idt_start :

    dw 0x00         ; The interrupt handler is located at absolute address 0x00
    dw CODE_SEG     ; CODE_SEG points to the GDT entry for code
    db 0x0          ; The unused byte
    db 0b11101001   ; 1110 Defines a 32 bit Interrupt gate, 0 is mandatory, privilege level = 0 (0b00), the last bit is one so that the CPU knows that the interrupt will be used
    dw 0x00         ; The higher part of the offset (0x00) is 0x00

idt_end:

idt_descriptor :
    dw idt_end - idt_start - 1 ; Size of our idt, always one less than the actual size
    dd idt_start ; Start address of our idt

Вот мой обработчик прерываний (расположен в абсолютном месте 0x00 в памяти):

ISR_0:
    push eax
    add [0x300], byte 
    mov al, 0x20
    out 0x20, al
    pop eax
    iret    
    times 512-($-$) db 0

Вот код, который я использую для входа в защищенный режим и загрузки GDT и IDT в память:

[bits 16]

switch_to_pm:

    cli
    lgdt [gdt_descriptor]
    lidt [idt_descriptor]
    mov eax, cr0
    or eax, 1
    mov cr0,eax
    jmp CODE_SEG:init_pm

[bits 32]

init_pm :

    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ebp, 0x90000
    mov esp, ebp
    sti
    call BEGIN_PM

Моя основная функция (которая проверяет значение 0x300) выглядит следующим образом:

void main() {
    char iii[15];
    int * aa = (int *)0x300;
    for (;;)
    {
        setCursor(0, 0);
        print(itoab(*aa, iii));
    }
}

Кстати, я с помощью дампа памяти проверил, что все загружено по правильному адресу и все именно там, где и ожидается. Например, 0x300 - это свободная часть памяти, используемая просто для упрощения моего кода.

Ответы на вопрос(1)

Ваш ответ на вопрос