Summary: This article mainly introduces the writing, installation, and use of interrupt service procedures in the C language. Since the writing of the hard interrupt service program involves hardware port reading and writing operation, the user directly and the hardware, the data (such as hardware port addresses, etc.) to be used during programming, which makes programmers and computers There is a "buffering" role between hardware devices, and, with assembly language, it is convenient to program the hardware programming. This article only describes the writing of soft interrupt programs. Keywords: soft interrupt, interrupt vector, interrupt vector table, TSR memory resident, DOS re-entry, interrupt request, segment address, offset, register, BIOS, DOS, SETVECT (), getVect (), Keep (), Disable (), enable (), genterrupt (), int86 (), Interrupt For general C language enthusiasts, how to use interrupt routines in C, this problem should be very familiar, for example, we can pass int86 () Function call 13H interrupts directly on the disk physical sector, or the 33H number can be invoked to display the mouse cursor on the screen through the INT86 () function. In fact, 13h is good, 33H, which is just some functions, the parameters of these functions pass through the registers of the CPU. The interrupt number is only the start memory unit indirectly pointing to the function of the function, saying that it is indirect, that is, the start segment address and offset of the function are calculated by the interrupt number by one method (specific Operation, the following will explain it). As a result, the programmer does not need to write the user's program with too much time, as long as setting the parameters in their own program, then call the BIOS or DOS's interrupt service program, greatly reduce the program. Development difficulty, shorten the program development cycle. So since the interrupt is a function, it can be called by the user, and the user is arbitrarily written. The first 1024 bytes of computer memory saves 256 interrupt vectors, and each interrupt vector accounts for 4 bytes, and the first two bytes saves the entry address offset of the interrupt service. The latter two bytes save the entry segment address of the interrupt program, as long as they are transferred into register IP and CS, they can transfer the interrupt service program to implement interrupt calls. Whenever the interrupt occurs, the CPU multiplies the interrupt number in 4, and obtains the interrupt vector address in the interrupt vector table, and then obtains the IP and CS values to go to the inlet address of the interrupt service program, call interrupt. This is the basic process of interrupt service programs through interrupt number. When the computer is started, the BIOS fills the basic interrupt into the interrupt vector table. After the DOS gets the system control, it is necessary to fill some interrupt vectors in the table, and modify a part of the BIOS interrupt vector. A portion of the interrupt vector is that the system is reserved for users, such as 60H to 67H, and users can write their own interrupt service programs into these interrupt vectors. Not only that, but users can change and improve the system existing interrupt vector. In C language, a new function type Interrupt is provided, specifically used to define interrupt service programs, such as interrupt service programs we can write: / * Example 1: Interrupt service program * / void interrupt INT60 () {PUTS ("This is an esample");} The function of the interrupt is to display a string, why not use the printf () function? This involves the issue of DOS, will be introduced later.
A simple interrupt service program is written, how to fill in its function entry address to the interrupt meter, so that when the interrupt is generated, it will be transferred to the interrupt service program to execute it? Here you need to use the setVect () and getvect () functions. SetVect () has two parameters: the entry address of the interrupt number and function, which is functionally installed to the specified function to the specified interrupt vector, the getVect () function has a parameter: interrupt number, return value is the entry address of the interrupt . Before installation interrupts, it is best to use the disable () function to turn off the interrupt to prevent new interrupts during the installation process. After the program is running confusion, after the installation is complete, use the enable () function to open interrupts, so that the program is running normally . Now we can enrich the above example: / * Example 2: Writing, installation and use of interrupt service programs * / # include
#include
#ifdef __cplusplus
#define __ARGU ...
#ELSE
#define __ARGU
#ENDIF
Void Interrupt INT60 (__ARGU) / * Interrupt Service Function * /
{
PUTS ("this is an esample");
}
Void Install (__ argu), int Num) / * Installation Interrupt * / {Disable (); / * Close Interrupt * / SetVect (NUM, FADD); / * Settings Interrupt * / Enable (); / * Open interrupt * /} void main () {install (INT60, 0X60); / * Install the INT60 function to 0x60 interrupt * / geninterrupt (0x60); / * Artificial 0x60 interrupt * /} has a certain experience of readers It is easy to get the execution result of the program: "this is an example!" Is displayed on the screen. These are described in writing and installing the interrupt service program. Talk below talks about the writing and use of the internal storage (TSR). In the C language, you can use the Keep () function to resident in memory. This function has two parameters: status and size. Size is the length of the memory, you can use size = _ss _SP / 16-_PSP, of course, this is also an estimated method, not accurate value. After the function is executed, the exit status information is saved in STATUS. For example, for the example above, "GenInterrupt (0x60);" rewritten into "Keep (0, _ss _SP / 16-_PSP);" After executing the program, this program is residing, after which In software or programming, as long as the 60H interrupt is used, the word "this is an example!" Is displayed on the screen. To restore the system's definition of the 60H interrupt, you can only restart your computer. The example above is actually very imperfect. It does not consider the status of the DOS system environment. It does not consider whether the program has resident in memory, and does not consider exiting memory residence. For the second question, it is also very easy to solve: the execution program starts to read a function interrupt entry address (such as 63H interrupt) to determine whether it is empty (NULL), if it is empty, set this address as non-empty Resident in memory, if it is non-empty, it has resided and exited the program. This step is very important, otherwise it will cause the system to crash due to repeated resident occupancy. As for other two problems, there are not many instructions here, and interested readers can refer to some books. Not only that, we can also call the memory resident program by using the hotkey under DOS. For example, after the "Hope Dictionary" comes with the "Hope Dictionary" to resident memory, press the CTRL F11 key at any time to activate the program, and the dictionary interface appears. There is a micro-process chip in the keyboard of the microcomputer, used to scan and detect the pressing and release status of each button. Most buttons have a scan code to inform the CPU current state, but some special keys such as PrintScreen, Ctrl Break will not generate scanning code, and directly generate interrupts. Because of this, we can point the interrupt number generated by Ctrl Break to our own written program entry address, then after the Ctrl Break is pressed, the system will call our own programs to execute, this is actually modified Interrupt vector of Ctrl Break. As for other buttons activation programs, the captured scan code can be used to interrupt the captured scan code in the 9H keyboard, which is not described here. For example, after executing the following program, return the DOS system, press Ctrl Break when arbitrary, turn red.
/? NEWINT (__ argu); / * Function declaration * / void install (*_ argu), int Num); int main () {install (newint, 0x1b); / * Ctrl Break interrupt number: 1bh * / Keyp (0, _SS (_ SP / 16) -_ psp); / * Resident Program * / Return 0;} void interrupt newint (__ argu) {textbackground (4); / * Setting the bottom color * / clrs CRSCR ( ); / * Clear screen * /} Void Install (__ argu), int Num) {Disable (); setVect (NUM, FADD); / * Settings interrupt * / enable ();} Due to 13H The interrupt is the disk interrupt service program provided by the BIOS. For applications under DOS, they are implemented by calling this interrupt. There are many viruses under DOS like to modify the 13H interrupt to destroy the system, for example, modify the 13H interrupt service program, change it to: / * Example 4: Viral program pseudo code * / void interrupt new13 (__ argu) {iF (Virus seizure conditions) {Modified entry parameters point to the virus program entry address; execute the virus code;} Call the original 13h interrupt;} As long as one software (such as edit.com, etc.) is operational and the virus session condition is mature The virus is activated. Of course, this will result in a reduction in available memory space, which is easy to discover by the user. Some "smart" viruses will modify other interrupt vectors, allowing the memory size and actual phase of the system report. There is also a virus that when the user is discovered to track it through some programs (such as Debug.com, etc., it will sneak away, and the basic principle is still related to the modified interrupt. The hard disk 0-faced 1 sector (Side 0 Cylinder 0 Sector 1) saves important boot information, once it is broken, the computer will not recognize the hard disk. We can write a program to prevent any software (including viruses) from performing "writing" operations to this area to a certain extent, and its basic principle is to modify the 13H interrupt vector and resident in memory. Monitor each detail of software (including viruses) to disk operation. Reader Please note: This program does not consider the exit of memory resident. If you want to recover 13H interrupt, restart your computer. / * Example 5: Main guidance sector protection, use Turbo C 2.0, mbsp.c * / # include
#include
#define stsize 8192
#define psp_ENV_PSP 0x2C # define para (x) ((fp_off (x) 15 >> 4)
Typedef struct {unsigned BP, DI, Si, DS, ES, DX, CX, BX, AX, IP, CS, Flags;} Interrupt_Parameter; Void Install (VoidRupt (* faddress) (), int Num); void Interrupt New13 (Interrupt_Parameter P); int main () {UNION Regs; unsigned mem; unsigned far * pointer; char far * stack; printf ("/ n << Master Boot Sector Protector >> Version 1.0 / n / n "); If (stack = malloc (stsize)) == null) {Printf (" not enough memory! / N "); exit (1);} if (getvect (0x62)! = Null) {printf (" Already installed! / N "); exit (1);} install (getVect (0x13), 0x62); install (new13, 0x13); Pointer = MK_FP (_PSP, PSP_ENV_PSP); FreeMem (* Pointer); segread (& SREGS) MEM = SREGS.DS Para (stack) -_ psp; setblock (_PSP, MEM); Keep (0, MEM); Return 0; Void Install (VOID INTERRUPT (* faddress) (), int Num) {Disable ); SetVect (NUM, FADDRESS); enable ();
Void Interrupt New13 (Interrupt_Parameter P) {p.ax = _ax; p.cx = _cx; p.dx = _dx; if (_ah == 0x03 && _CH == 0 && _ CL == 0x01 && _ DH == 0 && _ DL == 0x80) Return; enable () GenInterrupt (0x62); disable (); _ ax = p.ax; _cx = p.cx; _dx = p.dx; return;} Description: Before using this program, please: 1 Use anti-virus software to guide the sector , Memory and all files have a comprehensive scan, confident that there are no viruses in the computer; 2 readers with computer assembly language can write a new boot program, first reside in memory, then call the original bootstrap, In order to open the protection function before the virus has not obtained system control. Finally, the DOS system re-entry problem. DOS is a single user single task operating system. If the program is interrupted during the execution, it is possible to cause operational operation because it destroys the original program running environment, which is disastrous. When the interrupt is generated, the CPU immediately aborts the current program to perform an interrupt service program. If there is a call to the DOS interrupt in the interrupt service program (such as the 21H number interrupt) of DOS, this must rewrite the environmental global variable (for example The PSP program prefix will be changed to the PSP of the interrupt program being executed), so the original environment is destroyed, the original program cannot be implemented correctly. When the interrupt call is completed and returned, the result of the user is unexpected. So when writing an interrupt service program, the DOS system function call should be avoided, and Malloc (), printf (), Sprintf (), etc. should not appear in the interrupt service program in the C language. Reference: "C Advanced Utility Design" Wang Shiyuan, Tsinghua University Press, 1996.3