Configurando interrupções no modo protegido (x86)

Qual é o processo de configuração de interrupções no modo protegido?

este O link diz que se deve:

Crie espaço para a tabela do descritor de interrupçãoInforme à CPU onde está esse espaço (consulte o Tutorial do GDT: o lidt funciona da mesma maneira que o lgdt)Diga ao PIC que você não deseja mais usar os padrões do BIOS (consulte Programando os chips PIC)Escreva alguns manipuladores ISR (consulte Interrupt Service Routines) para IRQs e exceçõesColoque os endereços dos manipuladores ISR nos descritores apropriadosHabilite todas as interrupções suportadas na máscara IRQ (do PIC)

O terceiro passo não faz sentido para mim (olhei paraesta link, mas não havia nada a dizer ao PIC), então eu o ignorei e concluí as próximas duas etapas, apenas para ficar sem noção mais uma vez quando cheguei à etapa final. No entanto, pelo meu entendimento das interrupções, as duas etapas que eu não entendi estão relacionadas às interrupções de hardware do controlador PIC e não devem afetar as interrupções geradas pelo PIT no IRQ 0. Portanto, eu também ignorei essa etapa.

Quando corri meu código, ele compilou bem e até rodou em uma máquina virtual, mas a interrupção pareceu disparar apenas uma vez. Percebi então que não estava enviando EOI para o PIC, impedindo-o de causar mais interrupções. No entanto, adicionarmov al, 0x20 eout 0x20, al pouco antes dairet instrução causa falha na máquina virtual.

Aqui está o meu 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

Aqui está o meu manipulador de interrupção (localizado no local absoluto 0x00 na memória):

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

Este é o código que eu uso para entrar no modo protegido e carregar o GDT e o IDT na memória:

[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

Minha função principal (que verifica o valor de 0x300) é a seguinte:

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

A propósito, eu verifiquei usando um despejo de memória que tudo está carregado no endereço correto e tudo está exatamente onde é esperado. Por exemplo, 0x300 é uma parte livre da memória usada simplesmente para simplificar meu código.

questionAnswers(1)

yourAnswerToTheQuestion