.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 .global int129 .global int200 .global int140 .global int144 .global int145 .global int146 .global int170 .global int255 .global exc0 .global exc1 .global exc2 .global exc3 .global exc4 .global exc5 .global exc6 .global exc7 .global exc8 .global exc9 .global exc10 .global exc11 .global exc12 .global exc13 .global exc14 .global exc15 .global exc16 .global exc17 .global exc18 // 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 /* Once we arrived here the stack already contains 3x 32bit values, which will be poped by 'iret' - eflags - return code segment selector - return instruction pointer There are two possiblities concerning our stack position: a) if the interrupt occured while kernel code was executed we are on the same stack and have no clue about the stack alignment b) if the interrupt occured while user code was executed the configured tss.esp0 was used, in this case we are at the start of the esp0 stack. */ \ack //acknowledge interrupt //also remember that we will get new interrupts only //after iret or reenabling themn explicitly! push $0x666 //make room for potential C functions 'return value'. //we use eax already for esp (so we can context switch) push $0x0 //indicate if we want to return the value in ebx 0x0=NO 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 // remember THIS stack position and $-16,%esp // padding to align stack on 16byte boundary before CALL sub $8,%esp // ... push \num // pass in this interrupt number push %eax // pass in original %esp (saved just few lines before) call \func // call aligned mov %eax,%esp // use the %esp we got from c function pop %gs // pop everything back... pop %fs // ... pop %es pop %ds popa cmp $0x0,(%esp) je skip\num pop %ebx pop %ebx jmp ret\num skip\num: add $8,%esp // potentially set return value to eax to return to the caller ret\num: iret // pops the return instruction pointer, return code segment selector, and EFLAGS image from the stack .endm .macro excx num func mov %esp,%eax // remember THIS stack position and $-16,%esp // padding to align stack on 16byte boundary before CALL sub $8,%esp // ... push \num // pass in this interrupt number push %eax // pass in original %esp (saved just few lines before) call \func // call aligned jmp . .endm exc0: excx $0 exception_handle exc1: excx $1 exception_handle exc2: excx $2 exception_handle exc3: excx $3 exception_handle exc4: excx $4 exception_handle exc5: excx $5 exception_handle exc6: excx $6 exception_handle exc7: excx $7 exception_handle exc8: excx $8 exception_handle exc9: excx $9 exception_handle exc10: excx $10 exception_handle exc11: excx $11 exception_handle exc12: excx $12 exception_handle exc13: excx $13 exception_handle exc14: excx $14 exception_handle exc15: excx $15 exception_handle exc16: excx $16 exception_handle exc17: excx $17 exception_handle exc18: excx $18 exception_handle int0: intx ack0 $0 interrupt_handler int1: intx ack0 $1 interrupt_handler int2: intx ack0 $2 interrupt_handler int3: intx ack0 $3 interrupt_handler int4: intx ack0 $4 interrupt_handler int5: intx ack0 $5 interrupt_handler int6: intx ack0 $6 interrupt_handler int7: intx ack0 $7 interrupt_handler int8: intx ack0 $8 interrupt_handler int9: intx ack0 $9 interrupt_handler int10: intx ack0 $10 interrupt_handler int11: intx ack0 $11 interrupt_handler int12: intx ack0 $12 interrupt_handler int13: intx ack0 $13 interrupt_handler int14: intx ack0 $14 interrupt_handler int15: intx ack0 $15 interrupt_handler int128: intx ack0 $128 interrupt_handler int129: intx ack0 $129 interrupt_handler int140: intx ack0 $140 interrupt_handler int144: intx ack0 $144 interrupt_handler int145: intx ack0 $145 interrupt_handler int146: intx ack0 $146 interrupt_handler int255: intx ack0 $255 interrupt_handler int200: intx ack0 $200 interrupt_handler int170: intx ack0 $170 interrupt_handler