.global int0 .global int1 .global int2 .global int3 .global int4 .global int5 .global int6 .global int7 .global int8 .global int9 .global int10 .global int11 .global int12 .global int13 .global int14 .global int15 .global int128 // nothing to ack .macro ack0 .endm // ack master .macro ack1 push %eax // persist mov $0x20,%al out %al,$0x20 pop %eax // load original .endm // ack master and servant .macro ack2 push %eax // persist mov $0x20,%al out %al,$0xa0 // slave out %al,$0x20 // master pop %eax // load original .endm .macro intx ack num func \ack pusha //Push all standard registers 8 regs x 4bytes/32bit push %ds //Push data segment push %es //etc... push %fs push %gs mov %esp,%eax and $-16,%esp // padding to align stack on 16byte boundary before CALL push \num push \num push \num push %eax // pass in original %esp call \func mov %eax,%esp // use %esp we got pop %gs pop %fs pop %es pop %ds popa iret // pops the return instruction pointer, return code segment selector, and EFLAGS image from the stack .endm int0: intx ack1 $0 pit_handler int1: intx ack1 $1 kb_handler int2: intx ack1 $2 interrupt_handler int3: intx ack1 $3 interrupt_handler int4: intx ack1 $4 interrupt_handler int5: intx ack1 $5 interrupt_handler int6: intx ack1 $6 interrupt_handler int7: intx ack1 $7 interrupt_handler int8: intx ack2 $8 interrupt_handler int9: intx ack2 $9 interrupt_handler int10: intx ack2 $10 interrupt_handler int11: intx ack2 $11 interrupt_handler int12: intx ack2 $12 mouse_handler int13: intx ack2 $13 interrupt_handler int14: intx ack2 $14 interrupt_handler int15: intx ack2 $15 interrupt_handler int128: intx ack0 $128 interrupt_handler pit_handler: call pit_interrupt_handler push $0 push 8(%esp) push 16(%esp) call interrupt_handler add $12,%esp ret kb_handler: push %eax mov $0x0,%eax in $0x60,%al pop %eax push $0 push 8(%esp) push 16(%esp) call interrupt_handler add $12,%esp ret mouse_handler: push %eax mov $0x0,%eax in $0x60,%al pop %eax push $0 push 8(%esp) push 16(%esp) call interrupt_handler add $12,%esp ret