INTERRUPTS

can someone explain to me what an interrupt is and how
I would use one and what for in turbo pascal. Also do
you know where I can get information about interrupts
on the web?

Primarily Interrupts are events in the outside world, like receiption
of a character on the serial port which must be quickly written to a
buffer, or like pressing the keyboard where the keycode must be written
quickly into a buffer. In case of such an event the hardware alerts the
CPU and sends a dedicated number to it.

The CPU then saves the current processor status on the stack and the
address where it was interrupted. Then it fetches the number mentioned
above and makes a lookup in a special table, the interrupt vector table,
for the start address of the "interrupt handling procedure". When this
(preferably short) job is done, the CPU reads back the saved status
(registers, flags) from the stack and returns to the interrupted "main" job.

More about hardware interrupts see below.

Software Interrupts

The 8086 and its successors can have up to 256 of these interrupt
vectors in the interrupt vector table. Since only few are used by the
hardware (typically 16 on a PC) , the remaining interrupt vectors are
used by so called "SOFTWARE INTERRUPT VECTORS". You shall
know that the hardware event can be simulated by a special machine
command within a program, where the interrupt vector number is
delivered by the program.

These vectors are mainly used by system programs, like the BIOS and the
BDOS (the 2 most important parts of an operating system). Some of the
vectors are used by addon programs, like the mouse driver or the EMS
memory handler.

Their behaviour is not that of an interrupt, but the name is still used.
They are simple far procedure calls with a shorthand calling code. The
main benefit is: the user need not know the address of the service procedure
in memory, it is automatically looked up in the resident interrupt vector
table.

Each of these vectors can do a lot of different jobs, eg. read/write on disk
or paint chars on the screen or... To tell the particular routines within the
operating system / driver, what exactly to do, the desired action is mailed
with a number in a register, usually the AH register. The remaining registers
hold special data, eg. the character to write to the screen in the AL register
or an address in the BX register or a count in the CX register or... And this
kind of interrupts return usually a result in one of the registers. This is very
diistinct from the primary intention of Interrupts, where no registers are
allowed to be modified by the interrupt service routine.

The most important interrupt vectors on a PC (DOS) are
INT 33 = 21H = BDOS system call
INT 16 = 10H = BIOS screen call

You find ALL about the vectors and the necessary register behaviour in the
famous "Ralph Brown" interrupt list. The URL is found on the
TP-links site in chapter "information".

In Turbo Pascal and in most compatible compilers you have the "Registers"
record and the INTR(nn,regs) instruction. Another way to call software
interrupts is reserved for experienced programmers, who _know_ what
they are doing and therefore can use the built in ASM.



The default interrupt vectors
Some interrupt vectors are reserved by the CPU internally. For Pascal
programmers the most famous of them is the vector #0, which is automatically
issued by the CPU in case of a division overflow. Usually the handling
procedure is part of DOS or the BIOS, but application programs may
(Turbo Pascal actually do) redirect it into its own "flesh".

Others are:
#01H = trace interrupt, for debugging purposes (singlestep)
#02H = NMI, NonMaskableInterrupt. This is nothing for the application
   programmer, but for the system. It detects power failure or memory
   parity errors etc.
#03H = the debugger interrupt vector.
#04H = overflow interrupt.
With the 80286 and higher additional dedicated vectors were introduced,
eg. for memory access violations or other general protection faults.

Unfortunately the people who developed the IBM-PC did not follow the
rules of Intel to keep ALL VECTORS BELOW 1FH free. So there arised
several problems, which make the PC such a silly computer. One of them:
the vector #5 was occupied by the IBM developers for PrintScreen, but
it is now used by the CPU for some protection fault interrupt. The software
has to distinguish first which source caused the interrupt and then switch
to the proper routine.



More about hardware interrupts in the PC

The old PC XT had 8 distinct hardware interrupt inputs.
The mask register is at IO-address 21H (Port[$21])
Hardw. Vektor Purpose
0 08H timer 18.2Hz
1 09H keyboard
2 0AH general purp.
3 0BH COM2
4 0CH COM3
5 0DH general purp.
6 0EH diskette controller
7 0FH printer / general purpose

With the PC-AT a second interrupt controller circuit (PIC) was installed.
This was chained to the interrupt # 2 on the primary controller. Thus the
old #2 was no longer available (this is a very old Intel hardware restriction).
The mask register is at IO-address A1H (Port[$A1])
Hardw. Vektor Purpose
8 70H CMOS real time clock
9 71H wired to old int2 busline
10 72H general purp.
11 73H general purp.
12 74H pointing device (PS2 mouse)
13 75H 8087 math coprocessor
14 76H hard disk controller
15 77H (secondary IDE contrlr)

The "general purpose" interrupt vectors are normally used by network cards,
games ports or other add-on hardware. The IBM-PC is VERY POOR in this
context.

It is VERY WISE to leave the dedicated interrupt vectors totally untouched,
eg. the disk driver vectors and the timer. Sometimes the int 1 (vector 9) is
intercepted for special keyboard handling even by application level programs,
but it is very likely that those programs crash the whole system.

For the 18.2Hz timer it is not necessary to intercept the vector 08H, there
is a better way to use the 1CH vector.

With hardware interrupts it is necessary to send a final EOI command to
the PIC controller, on the high numbers you must send it to both controllers.
But this is not covered here in detail.



There is a special machine code available to inhibit a hardware interrupt
for a short piece of program, the CLI and STI  instructions. But they will
no longer be available for application level programs on the protected
mode operating systems, they are simply not allowed for programs
running in the protection level 3.

To write your own hardware interrupts with Pascal, use the
Procedure MyHardwareHandler(AX,BX,CX...); Interrupt;
feature of TP (and most other compilers). This saves the CPU status
on the stack automatically. You can communicate with the application
program using mailbox variables in the data segment (globally declared
variables), but not with registers.

You MUST hold your interrupt service routine short, it MUST NOT
have loops or other time / power consuming instructions. You MUST
NOT call system function, nor write to the screen with a BIOS function
(direct screen write to memory is allowed) nor make disk access...
While your interrupt service routine is running other interrupts are
disabled except you issue the STI explicitly. Still all lower priority
interrupt vectors are disabled until you send the EOI command to the
PIC. But this can be dangerous if there exists any chance that your
own event could occur meanwhile again, which will screw up the
interrupt calls.

Note: due to a bug in the Borland/Turbo Pascal runtime library
you can get troubles with Longints used in an interrupt service
procedure. This is a typical result of the
   smart-youngster-computer-guy
way of programming, where one programmer was proud of
OPTIMIZING his code, but forgot to tell his collegue about  the
fact that he now used the newer 80386 32-bit registers.

With protected mode operating systems you can get a lot of troubles
with interrupts, especially hardware interrupts.

Franz Glaser

Get your own free homepage