Assembly Tutorial
Hello coder! Yup, you got it...the thirth part
of this awesome tutorial.;) What are we going to discus? The Interrupt
table!!! Yeah! I hope you read the previous parts, because I assume you
know that stuff. Well, let's cut the crap, and get on with the new stuff!
Interrupts - Can we live without them?
Yeah, Yeah, Yeah...(like Pup says to Pacmeyer in PQ:
SWAT;)) I know...the answer is simple: We CAN NOT! Altough some weird coders
(including me;)) think they can bypass every single interrupt and address
all hardware manually, don't let them foul you! Don't feel embarresed when
you use int's.;) I feel kinda funny today...:) But apparently I'm not...okay,
back to serious mode.
When the CPU detects an interrupt signal, it stops the current activity
and jumps to a special routine, called an interrupt handler. This handler
then detects why the interrupt occured and takes the appropiate action.
When the handler is finished executing this action, it jumps back to the
interrupted process. Several levels or "types" of interrupts are supported,
ranging from 0 to 255. Each type has a reserved memory location, called
an interruptvector. The interruptvector points to the appropiate interrupt
handler. When two or more interrupts occure at the same time, the CPU uses
a priority system. The CPU can also disable interrupts during crucial parts
in a program. It can be done per level, but usually all interrupts are
disabled. When the CPU executes an interrupt handler, all interrupts with
the same or lower priority are disabled until the handler has finished.
This means that even an interrupt handler can be interrupted by an interrupt
with a higher priority level. The 256 priority levels supported by the
Intel 80x86-processors can be split into three categories:
1) Internal hardware-interrupts
2) External hardware-interrupts
3) Software-interrupts
I'll explain these three types below.
Internal Hardware-Interrupts
Internal hardware-interrupts are the result of certain
situations that occure during the execution of a program, eg. divide by
zero. The interrupt levels attached to each situation are stored in hardware
and can not be changed.
| Level
00h
01h
02h
03h
04h
05h
06h
07h
08h
09h
0Ah
0Bh
0Ch
0Dh
0Eh
0Fh
10h
11h-1Fh |
Situation
Divide by zero
Single Step
NMI
Breakpoint
Overflow
BOUND limit passed
Invalid opcode
Processor extension not available
Double exception
Segment limit passed
Invalid task status segment
Segment not present
Stacksegment limit passed
General protection error
Page fault
Reserved
Math coprocesst error
Reserved |
8086/88
X
X
X
X
X
-
-
-
-
-
-
-
-
-
-
-
-
- |
80286
X
X
X
X
X
X
X
X
-
X
X
X
X
X
X
-
-
X |
80386
X
X
X
X
X
X
X
X
-
X
X
X
X
X
X
X
-
X |
External Hardware-Interrupts
External hardware-interrupts are produced by controlers
of external devices or coprocessors and are linked to the processor pin
for Non Maskable Interrupts (NMI) or to the pin for Maskable Interrupts
(INTR). The NMI line is usually reserved for interrupts that occure because
of fatal errors like a parity error or a power distortion. Interrupts from
external devices can also be linked to the processor via the Intel 8259A
Programmable Interrupt Controller (PIC). The CPU uses a group of I/O ports
to control the PIC and the PIC puts its signals on the INTR pin. The PIC
makes it possible to enable or disable interrupts and to change the priority
levels under supervision of a program. One single PIC can handle eight
interrupt levels, but several 8259A PIC's can be coupled to support as
much levels as needed. 80286 and 80386 machines use two PIC's, wich can
together configure 16 interrupt levels. Ever wondered what that IRQ level
of your soundcard means? IRQ stands for Interrupt ReqQuest level, and as
you might've guessed, you have 16 IRQ's. The keyboard for example uses
IRQ 1 and the clock IRQ 0. This means that the clock has a higher priority
than the keyboard, so if you type something the clock won't stop. The instructions
STI and CLI can be used to enable/disable interrupts on the INTR pin, this
has no effect on NMI interrupts.
Software Interrupts
Software interrupts are the result of an INT instruction
in an executed program. This can be seen as a programmer triggered event
that immediately stops execution of the program and passes execution over
to the INT handler. The INT handler is usually part of the operating system
and will determine the action that should be taken (eg. output to screen,
execute file etc.) An example is INT 21h, wich is the DOS service interrupt.
When the handler is called it will read the value stored in AH (sometimes
even AL) and jumps to the right routine.
Interrupt Table and TSR basics
I mentioned before that each interrupt level has a
reserved memory location, called an interrupt vector. All these vectors
(or pointers) are stored in a table, the interrupt table. This table lies
at linear address 0, or with 64KB segments, at 0000:0000. Each vector is
2 words long (4 bytes). The high word contains the offset and the low word
the segment of the INT handler. Since there are 256 levels and each vector
is 4 bytes long, the table contains 1024 bytes (400h). The INT number is
multiplied by 4 to fetch the address from the table. A very useful property
of this system is that we can change the vectors to point to another routine.
This is in fact what a TSR (Terminate and Stay Resident) does. Suppose
we want to make our own "put string" (INT 21h AH=09 DS:DX=offset string)
routine. We could do this by making a procedure in our program and call
it when needed, but that's not what we want. We want every other program
writing to the screen this way use our routine. This can easily be achieved
by changing the INT 21h vector to point to our routine. We should write
the routine so, that it checks if AH=09 and if it's not it uses the old
vector. However there is one problem, as soon as the program to set this
up is finished the memory can be used again and will probably be overwritten
by the next program. This results in a jump into the middle of the overwriting
program when INT 21h is executed and will crash the system. We must find
some way to "lock" the memory. This can be achieved by using INT 27h (Terminate
and stay resident). When we end a program with INT 27h it will reserve
the memory the program runs in.
How INT's are processed
In fact most of this information can be get from the
rest of the text, but I wanted to make it a bit more clear. When the CPU
registeres an INT it will push the FLAGS register to the stack and it will
also push the CS and IP registers. After that the CPU disables the interrupt
system. Then it gets the 8-bit value the interrupting device sends and
multiplies this by 4 to get the offset in the interrupt table. From this
offset it gets the address of the INT handler and carries over execution
to this handler. The handler usually enables the interrupt system immediately,
to allow interrupts with higher priority. Some devices also need a signal
that the interrupt has been acknowledged. When the handler is finished
it must signal the 8259A PIC with an EOI (End Of Interrupt). This can be
done by sending 20h to port 20h. Then the handler executes an IRET instruction,
wich is the same as a RET instruction with the only difference that it
pops the FLAGS register too.
Closing words
All the above is true in real mode. In protected mode
it's generally the same, but there are some minor differences. For example
the IDT register contains the position of the INT table and the CPU pushes
EFLAGS, CS, EPI. I won't explain this here. If you really want to know
read my Protected Mode tutorial. I'm still writing it, so it's not available
yet. As always I hope you learned something from this. Please send me comments
and/or suggestions. My tutors can always be found at:
<< Previous || Next
>>