ISR :: Interrupt Service Routines |
The x86 architecture is an interrupt driven system. External events
are processed by interrupt service routines (ISR's) whose offsets
are stored in the IDT (interrupt descriptor table).
These events can be hardware driven interrupts or software driven interrupts. An example of a hardware ISR is the keyboard. Every time you press a key, the keyboard signales to the IRQ1 which runs an interrupt. An example of a software driven interrupt is the services provided by MS-DOS, they use INT 21h and are signalled by software when to run. |
Whats the difference between an ISR and normal routine? |
The difference between an ISR and a normal routine is very slight
and has to do with CPU opcodes.
ISR routines end their routine with an "Interrupt Return (IRET)" whereas normal procedures end their routines with "Return (RET)" or "Far Return (RETF)" Some compilers do not have the ability to correctly create ISRs. Often a compiler introduces a non ansi compliant keyword "_interrupt" or "interrupt". Compilers known to support this keyword are Watcom C/C++, Borland C/C++, Microsoft C 6.0. However, GCC does not support this keyword for x86 architecture and it would seem Visual C/C++ does not. /* example of clock tick routine in Watcom C/C++ */ void _interrupt ISR_clock(void) { clock_count++; } |
So how do I do an ISR in GCC? |
Doing an ISR in GCC is a little more complex than for compilers
that support the "_interrupt" keyword.
You have to write a small routine in assembler to call your C routine. /* Filename : isr_clock.s */ /* GCC AT&T asm example for ISR routine */ /* This example is for our clock_tick example */ /* NOTE! This example assumes nothing in regards to contents of registers on running */ .globl _clock_isr .align 4 _clock_isr: /* save some registers */ pushl %eax pushl %ds pushl %es pushl %fs pushl %gs /* set our descriptors up to a DATA selector */ movl $0x10, %eax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs /* call our clock routine */ call _ISR_clock /* clear the PIC (clock is a PIC interrupt) */ movl $0x20, %eax outb %al, $0x20 /* restor our regs */ popl %gs popl %fs popl %es popl %ds popl %eax iret /* filename : clock.c */ /* clock routine */ /* tell our linker clock_isr is not in this file */ extern void clock_isr(void); __volatile__ unsigned long clock_count=0L; void ISR_clock(void) { clock_count++; } |