/* assembly wrapper */
void asmstub_kbhandler(void);
__asm__
(
".text\n"
".globl asmstub_kbhandler\n"
"asmstub_kbhandler:\n"
"  pusha\n"          /* preserve registers */
"  call kbhandler\n"
"  popa\n"          /* restore register contents */
"  iret\n"          /* Interrupt RETurn */
);

/* C handler */
void kbhandler()
{
  /* must read port 60h on each keyboard interrupt,
so you can continue receiving keyboard interrupts */
  char byte = inb(0x60);

  kprintf("keyboard interrupt received\n");

  /* send end-of-interrupt to PIC for the same reason */
  outb(0x20, 0x20);
}

...
/* put the assembly stub in the IDT */
set_idt_entry(0x21, (unsigned int)asmstub_kbhandler);
