I have created an operating system from scratch, which accepts interruptions from the keyboard. However, when the keyboard is pressed, the kernel stops working. Any advice is appreciated.
Here's the code:
BootLoader.asm
[BITS 16]
[ORG 0x7C00]
READSECTOR EQU 0x64
READMEMORY EQU 0x7E00
Init:
    CLI
    XOR AX, AX
    MOV DS, AX
    MOV ES, AX
    MOV SS, AX
    MOV SP, 0x7C00
    MOV BP, SP
    STI
Main:
    CALL LoadKernel
    CALL SetVBE
    CALL DisableInt
    CALL EnableA20
    CALL SetupGDT
    CALL EnterProtectedMode
LoadKernel:
    MOV BYTE[BootDrive], DL
    MOV BX, 0x02
    MOV CX, READSECTOR
    MOV DX, READMEMORY
    MOV AH, 0x02
    MOV AL, CL
    MOV CL, BL
    MOV BX, DX
    MOV CH, 0x00
    MOV DH, 0x00
    MOV DL, BYTE[BootDrive]
    INT 0x13
    JC LoadFailed
    RET
LoadFailed:
    MOV SI, MsgBootFailed
    CALL Print
    CLI
    HLT
Print:
    MOV AH, 0x0e
    MOV BL, 0x07
    MOV BH, 0x00
PrintLoop:
    LODSB
    TEST AL, AL
    JZ PrintEnd
    INT 0x10
    JMP PrintLoop
PrintEnd:
    RET
SetVBE:
    MOV AL, 0x13
    MOV AH, 0x00
    INT 0x10
    RET
DisableInt:
    MOV AL, 0xff
    OUT 0x21, AL
    NOP
    OUT 0xa1, AL
    CLI
    RET
EnableA20:
    IN AL, 0x92
    OR AL, 2
    OUT 0x92, AL
    RET
SetupGDT:
    CLI
    PUSHA
    LGDT [GDT_TOC]
    STI
    POPA
    RET
GDT_TOC:
    DW 8 * 3
    DW GDT, 0x0000
GDT:
    DW 0x0000, 0x0000, 0x0000, 0x0000
    DW 0xFFFF, 0x0000, 0x9A00, 0x00CF
    DW 0xFFFF, 0x0000, 0x9200, 0x00CF
EnterProtectedMode:
    MOV EAX, CR0
    AND EAX, 0x7fffffff
    OR EAX, 1
    MOV CR0, EAX
    JMP 08h:Main32
[BITS 32]
Main32:
    MOV     AX, 0x10
    MOV     DS, AX
    MOV     ES, AX
    MOV     FS, AX
    MOV     GS, AX
    MOV     SS, AX
    MOV     ESP, 0xffff
    CALL RelocKernel
    JMP ExecuteKernel
RelocKernel:
    MOV ESI, READMEMORY
    MOV EDI, 0x200000
    MOV ECX, 512 * READSECTOR
    CALL memcpy
    RET
memcpy:
    MOV EAX, [ESI]
    ADD ESI, 4
    MOV [EDI], EAX
    ADD EDI, 4
    SUB ECX, 1
    JNZ memcpy
    RET
ExecuteKernel:
    CLI
    MOV EBP, 0x200000
    ;ADD EBP, [EBP + 0x18]
    CALL EBP
    HLT
MsgBootFailed: DB "Kernel Load Failed.", 0x0D, 0x0A, 0x00
BootDrive: DB 0
TIMES 510 - ($ - $$) DB 0
DW 0xAA55
KernelMain.c
#include "KernelMain.h"
int main()
{
    InitGDTIDT();
    InitPIC();
    ASM_STI();
    IoWrite8(0x0021, 0xf9);
    IoWrite8(0x00a1, 0xef);
    for (;;)
    {
        ASM_HLT();
    }
    return 0;
}
KernelMain.h
typedef unsigned long size_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned long long uint64_t;
#define ADR_IDT 0x0010f800
#define LIMIT_IDT 0x000007ff
#define ADR_GDT 0x00110000
#define LIMIT_GDT 0x0000ffff
#define ADR_KERNEL 0x00200000
#define LIMIT_KERNEL 0x0007ffff
#define AR_DATA32_RW 0x4092
#define AR_CODE32_ER 0x409a
#define AR_INTGATE32 0x008e
typedef struct
{
    uint16_t LimitLow;
    uint16_t BaseLow;
    uint8_t BaseMid;
    uint8_t AccessRight;
    uint8_t LimitHigh;
    uint8_t BaseHigh;
} SEGMENT_DESCRIPTOR;
typedef struct
{
    uint16_t OffsetLow;
    uint16_t Selector;
    uint8_t DwCount;
    uint8_t AccessRight;
    uint16_t OffsetHigh;
} GATE_DESCRIPTOR;
void InitGDTIDT();
void SetSegmentDescriptor(SEGMENT_DESCRIPTOR *sd, uint32_t limit, int base, int ar);
void SetGateDescriptor(GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
void InitPIC();
void _inthandler21(int *esp);
void _inthandler27(int *esp);
void _inthandler2c(int *esp);
void _asm_inthandler21(void);
void _asm_inthandler27(void);
void _asm_inthandler2c(void);
Segment.c
#include "KernelMain.h"
void InitGDTIDT()
{
    SEGMENT_DESCRIPTOR *gdt = (SEGMENT_DESCRIPTOR *)ADR_GDT;
    GATE_DESCRIPTOR *idt = (GATE_DESCRIPTOR *)ADR_IDT;
    int i;
    for (i = 0; i <= LIMIT_GDT / 8; i++)
    {
        SetSegmentDescriptor(gdt + i, 0, 0, 0);
    }
    SetSegmentDescriptor(gdt + 1, 0xffffffff, 0x00000000, AR_DATA32_RW);
    SetSegmentDescriptor(gdt + 2, LIMIT_KERNEL, ADR_KERNEL, AR_CODE32_ER);
    LoadGDT(LIMIT_GDT, ADR_GDT);
    for (i = 0; i <= LIMIT_IDT / 8; i++)
    {
        SetGateDescriptor(idt + i, 0, 0, 0);
    }
    LoadIDT(LIMIT_IDT, ADR_IDT);
    SetGateDescriptor(idt + 0x21, (int)_asm_inthandler21, 2 * 8, AR_INTGATE32);
    SetGateDescriptor(idt + 0x27, (int)_asm_inthandler27, 2 * 8, AR_INTGATE32);
    SetGateDescriptor(idt + 0x2c, (int)_asm_inthandler2c, 2 * 8, AR_INTGATE32);
}
void SetSegmentDescriptor(SEGMENT_DESCRIPTOR *sd, uint32_t limit, int base, int ar)
{
    if (limit > 0xfffff)
    {
        ar |= 0x8000;
        limit /= 0x1000;
    }
    sd->LimitLow = limit & 0xffff;
    sd->BaseLow = base & 0xffff;
    sd->BaseMid = (base >> 16) & 0xff;
    sd->AccessRight = ar & 0xff;
    sd->LimitHigh = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
    sd->BaseHigh = (base >> 24) & 0xff;
}
void SetGateDescriptor(GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
    gd->OffsetLow = offset & 0xffff;
    gd->Selector = selector;
    gd->DwCount = (ar >> 8) & 0xff;
    gd->AccessRight = ar & 0xff;
    gd->OffsetHigh = (offset >> 16) & 0xffff;
}
Interrupts.asm
[BITS 32]
    GLOBAL  _asm_inthandler21, _asm_inthandler27, _asm_inthandler2c
    EXTERN  _inthandler21, _inthandler27, _inthandler2c
[SECTION  .text]
_asm_inthandler21:
        PUSH    ES
        PUSH    DS
        PUSHAD
        MOV     EAX,ESP
        PUSH    EAX
        MOV     AX,SS
        MOV     DS,AX
        MOV     ES,AX
        CALL    _inthandler21
        POP     EAX
        POPAD
        POP     DS
        POP     ES
        IRETD
_asm_inthandler27:
        PUSH    ES
        PUSH    DS
        PUSHAD
        MOV     EAX,ESP
        PUSH    EAX
        MOV     AX,SS
        MOV     DS,AX
        MOV     ES,AX
        CALL    _inthandler27
        POP     EAX
        POPAD
        POP     DS
        POP     ES
        IRETD
_asm_inthandler2c:
        PUSH    ES
        PUSH    DS
        PUSHAD
        MOV     EAX,ESP
        PUSH    EAX
        MOV     AX,SS
        MOV     DS,AX
        MOV     ES,AX
        CALL    _inthandler2c
        POP     EAX
        POPAD
        POP     DS
        POP     ES
        IRETD
Interrupts.c
#include "KernelMain.h"
#define PIC0_ICW1 0x0020
#define PIC0_OCW2 0x0020
#define PIC0_IMR 0x0021
#define PIC0_ICW2 0x0021
#define PIC0_ICW3 0x0021
#define PIC0_ICW4 0x0021
#define PIC1_ICW1 0x00a0
#define PIC1_OCW2 0x00a0
#define PIC1_IMR 0x00a1
#define PIC1_ICW2 0x00a1
#define PIC1_ICW3 0x00a1
#define PIC1_ICW4 0x00a1
void InitPIC()
{
    IoWrite8(PIC0_IMR, 0xff);
    IoWrite8(PIC1_IMR, 0xff);
    IoWrite8(PIC0_ICW1, 0x11);
    IoWrite8(PIC0_ICW2, 0x20);
    IoWrite8(PIC0_ICW3, 1 << 2);
    IoWrite8(PIC0_ICW4, 0x01);
    IoWrite8(PIC1_ICW1, 0x11);
    IoWrite8(PIC1_ICW2, 0x28);
    IoWrite8(PIC1_ICW3, 2);
    IoWrite8(PIC1_ICW4, 0x01);
    IoWrite8(PIC0_IMR, 0xfb);
    IoWrite8(PIC1_IMR, 0xff);
    return;
}
void _inthandler21(int *esp)
{
    for (int i = 0; i < 320 * 200; i++)
    {
        *((uint8_t *)i) = 1;
    }
    for (;;)
    {
        ASM_HLT();
    }
}
void _inthandler2c(int *esp)
{
    for (int i = 0; i < 320 * 200; i++)
    {
        *((uint8_t *)i) = 2;
    }
    for (;;)
    {
        ASM_HLT();
    }
}
void _inthandler27(int *esp)
{
    for (int i = 0; i < 320 * 200; i++)
    {
        *((uint8_t *)i) = 3;
    }
    IoWrite8(PIC0_OCW2, 0x67);
    return;
}
asm.c
#include "KernelMain.h"
void IoWrite8(uint32_t port, uint8_t data)
{
    asm volatile("outb %b0, %w1"
                 :
                 : "a"(data), "Nd"(port));
}
uint8_t IoRead8(uint32_t port)
{
    uint8_t data;
    asm volatile("inb %w1, %b0"
                 : "=a"(data)
                 : "Nd"(port));
    return data;
}
void LoadGDT(int Limit, int Addr)
{
    asm volatile("mov    0x4(%esp),%ax");
    asm volatile("mov    %ax,0x6(%esp)");
    asm volatile("lgdtl  0x6(%esp)");
    return;
}
void LoadIDT(int Limit, int Addr)
{
    asm volatile("mov    0x4(%esp),%ax");
    asm volatile("mov    %ax,0x6(%esp)");
    asm volatile("lidtl  0x6(%esp)");
    return;
}
void ASM_HLT()
{
    asm volatile("HLT");
}
void ASM_CLI()
{
    asm volatile("CLI");
}
void ASM_STI()
{
    asm volatile("STI");
}
After trying for a while, I found that _asm_inthandler21 is probably not called when the keyboard is pressed.
 
    