Well, lets start off with this. Interrupt, as the name suggests, causes an interruption in the program temporarily and causes the processor to execute the statements according to the Interrupt generated. If you didn’t understand it, read on and you will come to know. But, it is important that you try to understand it.
Interrupts are basically of the two types one is hardware and another one is software. Hardware interrupt deals with a chip causing a Interrupt by signalling the microprocessor directly(through wires) on a microprocessor pin labelled INTR. And software interrupts, which we will be primarily dealing over here is generated by an ordinary software call. Let us first study basic about Interrupts.
In the Real mode memory system, first 1024 bytes of memory are reserved for Interrupt service routines addresses. Don’t be over-whelmed by that phrase. It isn’t that difficult. Let me tell you. Interrupt service routine is a piece of program which will execute when you(or the hardware) calls the Interrupt. And Interrupt service routine address is nothing but the segment:offset address of the Interrupt Service Routine(ISR, from now on). As the name segment:offset suggests, each carry 4 bytes of information and there is space for only 256 Interrupt calls or slots. These are like booking. You book your interrupt and reserve it for yourself. From then, you will know it by a number from 0 to 255. Then, when you need to call that interrupt, you simply tell the computer the Interrupt number and it does the work for you.
In Protected mode memory system, the Interrupts are defined quite differently. There are 256 Interrupts but for each 8 bytes are allocated making 2048 bytes in all. These are called Interrupt descriptors and they contain information like access rights, priveleges, etc. The entire table of these is called Interrupt Descriptor Table(IDT).
Let’s get back to Real mode memory system. I said 256 Interrupts and 4 bytes per interrupt, so 256 * 4 bytes = 1024 bytes. So, this table spans from location 00000h to 00400h. Suppose, you want to know the location of ISR of Interrupt number 50. Then, you multiply 50 * 4 = 200 and then access the 200th location in this part of memory; or 0:200 (not hexadecimal). Read 4 bytes from this location and you are done. You get the segment:offset pair.
And, if you want to ‘register’ your ISR, then simply write to the location. Again, if you want Interrupt number 50, then 50 * 4 = 200 and write to the location the segment:offset pair of your new ISR. There is another(and easier) way to write to this locations, read on and you will come to know.
With this, you are all set to write the code for your own Interrupts. But wait a minute, you need to know this. At the end of every ISR, you must execute the instruction IRET instead of RET. The processor, when calling the Interrupt, PUSHes the flags also on the stack and to account for that, IRET is used to return from an ISR. Also note that there will be 6 bytes PUSHed on the stack instead of 4(normal CALL). So, always use IRET.
Before you proceed, let me tell you one thing. To call a Interrupt, you just need to use the instruction INT followed by the Interrupt number you want to call. And now, the DOS way of setting Interrupts. It is done to the DOS Interrupt 21h function AH=25h and AH=35h.
Let us start with the Interrupt for getting ISR address. We use AH=35h for this. First set, AH=35h and AL=ISR routine of which you want address and DOS will return the ISR address or handler(as it is officially called) in ES:BX. Here’s some code.
Now in ES:BX you have the segment:offset pair of the ISR. Wait. As you see here, you use a Interrupt to set another Interrupt. There is nothing special about it, as I earlier said that Interrupts are just special calls but they execute normal ordinary instructions. So, don’t get confused.
And now, setting Interrupt vectors(or addresses). You use the function AH=25h. You first load the value of AH with 25h, AL with Interrupt number and DS:DX to the new segment:offset pair. DS contains the segment address and DX contains the offset. DS:DX is a pointer to the ISR itself. And with this, call INT 21h and Interrupt is set. Some code again.
mov ds,some segment
mov dx,some offset
That’s it. And let me tell you that you cannot directly put a value into a segment register like DS through memory or immediate addressing. It has to be done through some other register(AX, BX, CX, DX). So, bear that in mind.
You are nearly completed, now just some extra info. Hardware Interrupts are the same as software ones. The only difference is called through hardware on motherboard and given a priority. However, most of them follow the norms of the Software Interrupt in the field of coding.
And, to speed up the task of Interrupts, the Processor resets(0) the Trap flag in flags register so that Interrupt will go on faster. Trap flag is generally set(1) otherwise and it is used mainly for debugging purposes, slowing things. But, in Interrupts they are not allowed.
Finally, Interrupts are mainly used for purposes that require constant updates; like time, mouse, keyboard etc.. So that means, they keep Interrupting the processor always when your code is running. This slows up, the code to some (small) extent. However, if you want to disable those Interrupts to keep your code faster, you can use the STI instruction which disables all the Hardware Interrupts. To enable them again, use CLI. It is very important that you use CLI always otherwise, computer may hang as there will be no input from keyboard, mouse. Even the time will not run.