home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------------;
- ; ;
- ; Listing 1 ;
- ; ;
- ; NAME : SYS_PROF ;
- ; ;
- ; DATE : March 24, 1988 ;
- ; ;
- ; AUTHOR : (C) Copyright 1988 G. Kent Cobb - All Rights Reserved ;
- ; ;
- ; DESCRIPTION : ;
- ; This is the terminate-and-stay-resident portion of a system profiler. ;
- ; It installs several interrupt handlers, which monitor the occurrences ;
- ; and duration of a number of software interrupts. ;
- ; ;
- ;-----------------------------------------------------------------------------;
-
- ;----------------------------------------------------------------------------;
- ; Interrupt numbers ;
- ;----------------------------------------------------------------------------;
-
- TIMER_INTERRUPT EQU 1CH
- TERMINATE EQU 20H
- TERM_AND_STAY_RES EQU 27H
- CONTROL_INTERRUPT EQU 60H
-
- ;----------------------------------------------------------------------------;
- ; MS-DOS functions (Interrupt 21H services) ;
- ;----------------------------------------------------------------------------;
-
- DOS MACRO OP
- MOV AH,DOS_&OP
- INT 21H
- ENDM
-
- DOS_DISPLAY_STRING EQU 09H
- DOS_SET_INT_VECTOR EQU 25H
- DOS_GET_INT_VECTOR EQU 35H
-
- ;----------------------------------------------------------------------------;
- ; This is a list of all the interrupts that are intercepted by SYS_PROF. ;
- ;----------------------------------------------------------------------------;
-
- NUMBER_OF_INTERRUPTS EQU 9
-
- PRINT_SCREEN_INTERRUPT EQU 5H
- VIDEO_INTERRUPT EQU 10H
- DISK_INTERRUPT EQU 13H
- COMM_INTERRUPT EQU 14H
- KEYBOARD_INTERRUPT EQU 16H
- PRINTER_INTERRUPT EQU 17H
- DOS_FUNC_INTERRUPT EQU 21H
- ABS_DISK_READ_INTERRUPT EQU 25H
- ABS_DISK_WRITE_INTERRUPT EQU 26H
-
-
- ;----------------------------------------------------------------------------;
- ; These are the number of distinct services defined for each interrupt. ;
- ; The OCCURRENCES array contains two double words for each service, and ;
- ; two additional double words for each interrupt. If an interrupt is ;
- ; generated with a service number that is out of range, the data for it ;
- ; will accumulate in this additional bin. ;
- ;----------------------------------------------------------------------------;
-
- PRINT_SCREEN_SERVICES EQU 0
- VIDEO_SERVICES EQU 20
- DISK_SERVICES EQU 24
- COMM_SERVICES EQU 4
- KEYBOARD_SERVICES EQU 3
- PRINTER_SERVICES EQU 3
- DOS_FUNC_SERVICES EQU 99
- ABS_DISK_READ_SERVICES EQU 0
- ABS_DISK_WRITE_SERVICES EQU 0
-
- ;-----------------------------------------------------------------------;
- ; This macro defines the handling of the intercepted interrupts. The ;
- ; INT_NUM parameter that the macro expects is an index into the ;
- ; MAX_SERVICES and OFFSETS tables. ;
- ; ;
- ; Interrupts 25H and 26H are handled in a manner which is very ;
- ; similar, but slightly different from the other interrupts. If this ;
- ; macro is invoked with a second parameter, code is included to ;
- ; provide the special handling that these interrupts require. ;
- ;-----------------------------------------------------------------------;
-
- PERFORM_INTERRUPT MACRO INT_NUM,SPECIAL
-
- INTERRUPT_HANDLER&INT_NUM PROC FAR
-
- ; Turn interrupts back on.
-
- STI
-
- ; Save the existing interrupt and service numbers on the stack.
-
- PUSH CS:WORD PTR INTERRUPT
-
- ; Push the flags onto the stack now (before we execute any instructions which
- ; might change them) in order to simulate an interrupt later.
-
- PUSHF
-
- ; Save the value of WATCH on the stack while we're changing INTERRUPT and
- ; SERVICE.
-
- PUSH CS:WATCH
-
- ; Turn accumulation off, set new INTERRUPT and SERVICE values, make sure
- ; the service number is valid, and then restore accumulation to its previous
- ; state.
-
- MOV CS:WATCH,0
- MOV CS:INTERRUPT,&INT_NUM
- MOV CS:SERVICE,AH
- CALL VALIDATE_SERVICE
- POP CS:WATCH
-
- ; If accumulation is turned off, go straight to the real ISR.
-
- CMP CS:WATCH,0
- JE READY_FOR_INTERRUPT&INT_NUM
-
- ; If accumulation is turned on, push a one onto the stack to tell the
- ; ACCUMULATE routine which bin to increment, and then call it.
-
- PUSH CS:ONE
- CALL ACCUMULATE
-
- READY_FOR_INTERRUPT&INT_NUM:
-
- ; After tabulating occurrence data, execute the real ISR
-
- CALL CS:DWORD PTR OLD_INTERRUPT_VECTORS [ 4*(&INT_NUM-1) ]
-
- ; Interrupts 25H and 26H require special handling. Since they leave the
- ; flags on the stack when they return control to the calling program, we
- ; have an extra word on the stack which must be popped.
-
- IFNB <SPECIAL>
- POP CS:EXTRA_FLAGS
- ENDIF
-
- ; On return, pop the interrupt and service numbers that were current before
- ; this one.
-
- POP CS:WORD PTR INTERRUPT
-
- ; For most interrupts, return with RET 2 rather than IRET. This will
- ; preserve whatever treatment the real ISR uses for the flags.
-
- IFB <SPECIAL>
- RET 2
-
- ; Interrupts 25H and 26H are special cases. The calling program expects the
- ; flags to still be on the stack, so we use RET instead.
-
- ELSE
- RET
- ENDIF
-
- INTERRUPT_HANDLER&INT_NUM ENDP
-
- ENDM
-
-
-
- CODE_SEG SEGMENT PUBLIC
- ASSUME CS:CODE_SEG , DS:CODE_SEG
-
- ;-----------------------------------------------------------------------;
- ; This is the entry point for the program. Control is immediately ;
- ; transferred to the initialization code, which is located in the ;
- ; portion of the program which does not remain resident. ;
- ;-----------------------------------------------------------------------;
-
- ORG 100H ; COM FILE
-
- JUMP_TO_INIT PROC FAR
- JMP INIT
- JUMP_TO_INIT ENDP
-
-
- ;-----------------------------------------------------------------------------;
- ; The handling for all nine intercepted interrupts is very similar, and is ;
- ; defined by the PERFORM_INTERRUPT macro. This section contains the macro ;
- ; calls. ;
- ;-----------------------------------------------------------------------------;
-
- ; Print screen interrupt
-
- PERFORM_INTERRUPT 1
-
- ; BIOS Video interrupt
-
- PERFORM_INTERRUPT 2
-
- ; BIOS Disk interrupt
-
- PERFORM_INTERRUPT 3
-
- ; BIOS Comm interrupt
-
- PERFORM_INTERRUPT 4
-
- ; BIOS Keyboard interrupt (16H)
-
- PERFORM_INTERRUPT 5
-
- ; BIOS Printer interrupt
-
- PERFORM_INTERRUPT 6
-
- ; DOS Function calls interrupt
-
- PERFORM_INTERRUPT 7
-
- ; The last two interrupts, 25H and 26H, require special handling since the
- ; real ISRs do not pop the flags from the stack upon completion. By passing
- ; a second parameter to the PERFORM_INTERRUPT macro, the code to handle this
- ; will be included by the preprocessor when the macro is expanded.
-
- ; DOS Absolute disk read interrupt
-
- PERFORM_INTERRUPT 8 SPECIAL
-
- ; DOS Absolute disk write interrupt
-
- PERFORM_INTERRUPT 9 SPECIAL
-
- ;-----------------------------------------------------------------------;
- ; This routine is a piggyback ISR for interrupt 1C. It tabulates ;
- ; the current interrupt and service numbers if WATCH is non-zero, ;
- ; and then executes the real ISR. ;
- ;-----------------------------------------------------------------------;
-
- NEW_TIMER PROC NEAR
-
- STI
- CMP CS:WATCH,0 ; check to see if we accumulate
- JE DO_OLD_INT1C ; skip accumulate if 0
- PUSH CS:ZERO ; Push parameter onto stack
- CALL ACCUMULATE ; if not 0, accumulate data
-
- DO_OLD_INT1C:
- JMP CS:DWORD PTR OLD_INT1C ; jump to old interrupt 1C
-
- NEW_TIMER ENDP
-
-
- ;-----------------------------------------------------------------------;
- ; This routine validates the service number that is stored in the ;
- ; memory location SERVICE. For each interrupt, there is a maximum ;
- ; service number which is meaningful. This routine obtains that ;
- ; number from the MAX_SERVICES array, and compares it to the value of ;
- ; SERVICE. If SERVICE is not between zero and MAX - 1, inclusive, it ;
- ; is reset to MAX. All services which are requested with invalid or ;
- ; unknown service numbers will then accumulate in an "Other" bin. ;
- ;-----------------------------------------------------------------------;
-
- VALIDATE_SERVICE PROC NEAR
-
- PUSH BX ; Save BX register
-
- MOV BL,CS:INTERRUPT ; Retrieve the interrupt number
- XOR BH,BH
- DEC BX ; Adjust indexing to zero-based
- MOV BL,CS:MAX_SERVICE[BX]
- ; Get the maximum service number for this int
- CMP BL,CS:SERVICE ; Compare to current service number
- JG SERVICE_VALID ; If BL is greater, everything is OK
- MOV CS:SERVICE,BL ; Otherwise, set the service to the maximum #
- SERVICE_VALID:
- POP BX ; Restore BX register and return
- RET
-
- VALIDATE_SERVICE ENDP
-
- ;-----------------------------------------------------------------------;
- ; This routine increments a counter in the data table. It uses the ;
- ; current interrupt and service numbers to determine the proper loca- ;
- ; tion within the table. Either of two counters may be incremented, ;
- ; depending on the value of the parameter passed in on the stack. If ;
- ; the routine is called from the timer tick ISR, the parameter will ;
- ; be zero, and the first of the two will be incremented. If it is ;
- ; called from one of the software ISRs, the parameter will be one, ;
- ; and the second will be incremented instead. ;
- ;-----------------------------------------------------------------------;
-
- ACCUMULATE PROC NEAR
-
- PUSH BP
- MOV BP,SP ; Establish local stack frame
-
- PUSH AX
- PUSH BX ; push registers
-
- ; Calculate offset into the table of occurrences.
-
- MOV BL,CS:INTERRUPT ; move code for interrupt currently being
- ; serviced into bl
- XOR BH,BH ; zero out bh
- SHL BX,1 ; Multiply by two since OFFSETS are words.
- MOV BX,CS:OFFSETS[BX] ; Get the offset into the accumulation table
- MOV AL,CS:SERVICE ; move code for service currently being
- ; performed into al
- XOR AH,AH ; zero out ah
- SHL AX,1 ; multiply by 4 to convert number of
- SHL AX,1 ; double words to number of bytes
- SHL AX,1 ; multiply by 2 since there are two double
- ; words for each service
- ADD BX,AX ; add offset to get offset of data for this
- ; service
- CMP WORD PTR [BP+4],0 ; Is the parameter zero?
- JE INC_DOUBLE ; If yes, increment the first double word
- ADD BX,4 ; But if not, increment the second
- INC_DOUBLE:
-
- INC CS:WORD PTR [BX] ; Increment low-order word
- JNZ NO_CARRY
- ADD BX,2 ; If counter rolls over, increment high-
- INC CS:WORD PTR [BX] ; order word also
-
- NO_CARRY:
-
- POP BX ; Restore registers
- POP AX
-
- POP BP ; Restore old stack frame
- RET 2
-
- ACCUMULATE ENDP
-
- ;-----------------------------------------------------------------------;
- ; This is the service routine for the SYS_PROF control interrupt. It ;
- ; provides the following services: ;
- ; ;
- ; AH=0 : Report on/off status in AX ;
- ; AH=1 : Turn accumulation off ;
- ; AH=2 : Turn accumulation on ;
- ; AH=3 : Return address of data table in ES:BX ;
- ; AH=4 : Reset data table to zeroes ;
- ; ;
- ; These services are used by the PROFCTRL program to control the ;
- ; operations of SYS_PROF. ;
- ;-----------------------------------------------------------------------;
-
- CONTROL_ISR PROC NEAR
-
- STI ; Enable interrupts
- PUSH CX ; Save registers
- PUSH DI
- CMP AH,0 ; Is AH equal to 0?
- JG AH_NOT_0 ; No, skip to next test
-
- ; If we get to this point, AH is zero, which indicates that we should
- ; report the status of the accumulation flag.
-
- MOV AX,CS:WATCH
- JMP CONTROL_COMPLETE
-
- AH_NOT_0:
-
- CMP AH,1 ; Is AH equal to 1?
- JG AH_NOT_1 ; No, skip to next test
-
- ; If we get to this point, AH is one, which indicates that accumulation
- ; is to be turned off.
-
- MOV CS:WATCH,0 ; Turn off accumulation
- JMP OK
-
- AH_NOT_1:
-
- CMP AH,2 ; Is AH equal to 2?
- JG AH_NOT_2 ; No, skip to next test
-
- ; If we get to this point, AH is two, which indicates that accumulation
- ; is to be turned on.
-
- MOV CS:WATCH,1 ; Turn accumulation on
- JMP OK
-
- AH_NOT_2:
-
- CMP AH,3 ; Is AH equal to 3?
- JG AH_NOT_3 ; No, skip to next test
-
- ; If we get to this point, AH is three, which indicates that the segmented
- ; address of the data accumulation table should be returned in ES:BX.
-
- MOV BX,CS
- MOV ES,BX ; es = cs
- MOV BX,OFFSET OCCURRENCES
- ; offset of data table
- JMP OK
-
- AH_NOT_3:
-
- CMP AH,4 ; Is AH equal to 4?
- JG BAD_VALUE ; No, it must be invalid.
-
- ; If we get to this point, AH is four, which indicates that the data table
- ; should be reset to zeroes.
-
- PUSH ES ; Save current value of ES
- MOV CS:WATCH,0 ; Don't want to accumulate while we're re-initializing
- MOV AX,CS
- MOV ES,AX ; Make es = cs in order to use STOSW instruction
- MOV DI,OFFSET OCCURRENCES
- ; DI is set to start of data table for same reason
- MOV CX,OFFSET END_OF_TABLE
- SUB CX,DI
- SHR CX,1 ; CX contains number of words to zero
- CLD
- XOR AX,AX
- REP STOSW ; Zero the data table
- POP ES ; Restore ES
- JMP OK
-
- BAD_VALUE:
-
- MOV AH,0FFH ; Set AH to -1 to indicate error
- JMP CONTROL_COMPLETE
-
- OK:
-
- XOR AH,AH ; Set AH to 0 to indicate success
-
- CONTROL_COMPLETE:
-
- POP DI ; Restore registers
- POP CX
- IRET
-
- CONTROL_ISR ENDP
-
-
-
- ;-----------------------------------------------------------------------;
- ; DATA AREA ;
- ;-----------------------------------------------------------------------;
-
- ;-----------------------------------------------------------------------;
- ; This variable controls data accumulation. Service requests and ;
- ; timer ticks are tabulated if it is non-zero. ;
- ;-----------------------------------------------------------------------;
-
- WATCH DW 0
-
- ;-----------------------------------------------------------------------;
- ; The indices of the interrupt and service currently being performed ;
- ; are stored in this location. ;
- ;-----------------------------------------------------------------------;
-
- INTERRUPT DB 0
- SERVICE DB 0
-
- ;-----------------------------------------------------------------------;
- ; This array is used to store the segmented addresses of all the real ;
- ; interrupt service routines. It is initialized by ;
- ; REPLACE_SYSTEM_INTERRUPTS, and is used in the PERFORM_INTERRUPT ;
- ; macro. ;
- ;-----------------------------------------------------------------------;
-
- OLD_INTERRUPT_VECTORS DD 10 DUP(0)
-
- ;-----------------------------------------------------------------------;
- ; This table has one entry for each interrupt that is intercepted by ;
- ; SYS_PROF. The entry for a particular interrupt contains the number ;
- ; of distinct services that can be requested in AH. The values in the;
- ; table are checked by the VALIDATE_SERVICE routine to prevent ;
- ; corruption of the data tabulation process. ;
- ;-----------------------------------------------------------------------;
-
- MAX_SERVICE DB PRINT_SCREEN_SERVICES
- DB VIDEO_SERVICES
- DB DISK_SERVICES
- DB COMM_SERVICES
- DB KEYBOARD_SERVICES
- DB PRINTER_SERVICES
- DB DOS_FUNC_SERVICES
- DB ABS_DISK_READ_SERVICES
- DB ABS_DISK_WRITE_SERVICES
-
- ;-----------------------------------------------------------------------;
- ; This area is used to tabulate the number of request for each ;
- ; service, and the timer ticks that occur during each service. ;
- ;-----------------------------------------------------------------------;
-
- OCCURRENCES LABEL DWORD
- OTHER_BIN DD 2 DUP (0)
- PRINT_SCREEN_BIN DD 2*(1+PRINT_SCREEN_SERVICES) DUP (0)
- VIDEO_BIN DD 2*(1+VIDEO_SERVICES) DUP (0)
- DISK_BIN DD 2*(1+DISK_SERVICES) DUP (0)
- COMM_BIN DD 2*(1+COMM_SERVICES) DUP (0)
- KEYBOARD_BIN DD 2*(1+KEYBOARD_SERVICES) DUP (0)
- PRINTER_BIN DD 2*(1+PRINTER_SERVICES) DUP (0)
- DOS_FUNC_BIN DD 2*(1+DOS_FUNC_SERVICES) DUP (0)
- ABS_DISK_READ_BIN DD 2*(1+ABS_DISK_READ_SERVICES) DUP (0)
- ABS_DISK_WRITE_BIN DD 2*(1+ABS_DISK_WRITE_SERVICES) DUP (0)
- END_OF_TABLE LABEL DWORD
-
- ;-----------------------------------------------------------------------;
- ; This is a table of offsets into the previous table. It defines the ;
- ; offset of the start of the data area for each interrupt. ;
- ;-----------------------------------------------------------------------;
-
- OFFSETS LABEL WORD
- DW OTHER_BIN
- DW PRINT_SCREEN_BIN
- DW VIDEO_BIN
- DW DISK_BIN
- DW COMM_BIN
- DW KEYBOARD_BIN
- DW PRINTER_BIN
- DW DOS_FUNC_BIN
- DW ABS_DISK_READ_BIN
- DW ABS_DISK_WRITE_BIN
-
-
-
-
- OLD_INT1C EQU $ ; address of old timer interrupt
- OLD_OFS DW ? ; offset of old timer interrupt
- OLD_SEG DW ? ; segment of old timer interrupt
-
- ZERO DW 0
- ONE DW 1
- EXTRA_FLAGS DW 0
-
- ;-----------------------------------------------------------------------;
- ; This is the main routine of the initialization section. It replaces;
- ; several interrupt vectors, and then terminates, leaving the data ;
- ; tables and the interrupt service routines resident. ;
- ;-----------------------------------------------------------------------;
-
-
- INIT PROC NEAR
-
- ; Use internal stack during initialization
-
- MOV SP,OFFSET END_STACK
-
- ; Display copyright notice
-
- MOV DX,OFFSET COPYRIGHT_NOTICE
- DOS DISPLAY_STRING
-
- ; Install interrupt handlers.
-
- CALL INSTALL_CONTROL_INTERRUPT
- CALL REPLACE_TIMER
- CALL REPLACE_SYSTEM_INTERRUPTS
-
- ; Terminate and stay resident
-
- MOV AX,CS
- MOV DS,AX
- MOV DX,OFFSET INIT + 100H
- INT TERM_AND_STAY_RES
- INIT ENDP
-
-
-
- ;-----------------------------------------------------------------------;
- ; This routine initializes the interrupt vector for the SYS_PROF ;
- ; control interrupt. If it has been initialized previously (as ;
- ; indicated by a non-zero value), SYS_PROF will terminate without ;
- ; remaining resident. This makes it possible to run SYS_PROF several ;
- ; times in succession without taking up additional memory each time, ;
- ; and without checking beforehand to see if it is already resident. ;
- ;-----------------------------------------------------------------------;
-
- INSTALL_CONTROL_INTERRUPT PROC NEAR
-
- ; Get the current value of control interrupt vector to make sure something
- ; else doesn't use it already.
-
- MOV AL,CONTROL_INTERRUPT ; interrupt number in AL
- DOS GET_INT_VECTOR ; dos function call to get interrupt vector
- OR BX,BX ; is bx 0?
- JNE ERROR_EXIT ; if not, don't install anything
- MOV BX,ES ; bx = es
- OR BX,BX ; is es 0?
- JNE ERROR_EXIT ; if not, don't install anything
-
- ; Set control interrupt vector to the address of CONTROL_ISR.
-
- MOV BX,CS
- MOV DS,BX ; ds = cs
- MOV DX,OFFSET CONTROL_ISR ; move offset of new routine into dx
- MOV AL,CONTROL_INTERRUPT ; interrupt number in al
- DOS SET_INT_VECTOR ; dos function call to set interrupt vector
-
- RET
-
- ; This branch is taken if there is already something in the control
- ; interrupt vector.
-
- ERROR_EXIT:
-
- MOV DX,OFFSET ERROR_MESSAGE
- DOS DISPLAY_STRING ; Display the error message on the screen
- INT TERMINATE ; Terminate without staying resident
-
- INSTALL_CONTROL_INTERRUPT ENDP
-
-
- ;-----------------------------------------------------------------------;
- ; This routine changes the interrupt vector for interrupt 1C. The ;
- ; old interrupt vector is saved for future use, and the address of ;
- ; the NEW_TIMER routine replaces it in the interrupt vector table. ;
- ;-----------------------------------------------------------------------;
-
-
- REPLACE_TIMER PROC NEAR
-
- ; Get the existing timer interrupt vector.
-
- MOV AL,TIMER_INTERRUPT ; interrupt number in AL
- DOS GET_INT_VECTOR ; dos function call to get interrupt vector
- MOV CS:OLD_OFS,BX ; save old offset
- MOV CS:OLD_SEG,ES ; and segment
-
- ; Now overwrite the old interrupt vector with a new one.
-
- MOV BX,CS
- MOV DS,BX ; ds = cs
- MOV DX,OFFSET NEW_TIMER ; move offset of new routine into dx
- MOV AL,TIMER_INTERRUPT ; interrupt number
- DOS SET_INT_VECTOR ; dos function call to set interrupt vector
-
- RET
- REPLACE_TIMER ENDP
-
-
- ;-----------------------------------------------------------------------------;
- ; ;
- ; This routine replaces several interrupt vectors with the addresses of ;
- ; SYS_PROF's piggyback ISRs. The interrupts whose ISR's are to be ;
- ; replaced are found in the INT_NUMS array; the addresses of the piggyback ;
- ; ISRs are found in the NEW_ISR_ADDRESS array; and the old interrupt vectors;
- ; are stored in the OLD_INTERRUPT_VECTORS array. ;
- ; ;
- ; If a particular entry in the INT_NUMS table is zero, the replacement of ;
- ; that interrupt vector is skipped. ;
- ; ;
- ;-----------------------------------------------------------------------------;
-
- REPLACE_SYSTEM_INTERRUPTS PROC NEAR
-
- ; Initialize registers. CX will contain the number of interrupts to be
- ; intercepted, SI will point to the table which will contain the old
- ; interrupt vectors, and DI will contain the offset into the tables.
-
- MOV CX,NUMBER_OF_INTERRUPTS
- MOV SI,OFFSET OLD_INTERRUPT_VECTORS
- MOV DI,0
-
- ; This loop will be repeated for each interrupt that is to be intercepted.
-
- REPLACE_INTERRUPT_LOOP:
-
- PUSH DI ; Save DI
-
- ; If the interrupt number in the INT_NUMS table is zero, this one should be
- ; skipped.
-
- CMP INT_NUMS[DI],0
- JE END_OF_LOOP
-
- ; The routine REPLACE_INTERRUPT_VECTOR expects three parameters: the address
- ; of the new ISR, the interrupt number, and the storage location for the
- ; original interrupt vector. They are pushed onto the stack in reverse order.
-
- PUSH SI ; Push offset into old-vector table
- MOV AL,INT_NUMS[DI]
- XOR AH,AH
- PUSH AX ; Push interrupt number
- SHL DI,1
- PUSH NEW_ISR_ADDRESS[DI] ; Push table index
- CALL REPLACE_INTERRUPT_VECTOR ; Replace the interrupt vector
- ADD SP,4 ; Clean up the stack and restore
- POP SI ; SI in the process
-
- ; This section increments the pointers before the next iteration.
-
- END_OF_LOOP:
- POP DI
- INC DI
- ADD SI,4
- LOOP REPLACE_INTERRUPT_LOOP
-
- ; Return to calling routine.
-
- RET
-
- REPLACE_SYSTEM_INTERRUPTS ENDP
-
-
-
- ;-----------------------------------------------------------------------------;
- ; ;
- ; This routine will replace a single interrupt vector. The location of the ;
- ; new ISR, the interrupt number, and a location at which to store the old ;
- ; interrupt vector are passed in on the stack. ;
- ; ;
- ;-----------------------------------------------------------------------------;
-
- REPLACE_INTERRUPT_VECTOR PROC NEAR
-
- PUSH BP
- MOV BP,SP ; Establish local stack frame
-
- ; Save the old interrupt vector
-
- MOV AX,[BP+6] ; Interrupt number into AL
- DOS GET_INT_VECTOR ; Use DOS call to get interrupt vector
- MOV DI,[BP+8] ; Move the safe storage address into DI
- MOV CS:[DI],BX ; Save the offset
- MOV CS:[DI+2],ES ; Save the segment
-
- ; Now replace the interrupt vector
-
- MOV DX,CS
- MOV DS,DX ; ds = cs
- MOV DX,[BP+4] ; Move offset into DX
- MOV AX,[BP+6] ; Interrupt number into AL
- DOS SET_INT_VECTOR ; Use DOS call to set interrupt vector
-
- ; Restore old stack frame and return
-
- MOV SP,BP
- POP BP
- RET
-
- REPLACE_INTERRUPT_VECTOR ENDP
-
- ;-----------------------------------------------------------------------------;
- ; This data is necessary only for initialization, and does not need to ;
- ; remain resident. ;
- ;-----------------------------------------------------------------------------;
-
- COPYRIGHT_NOTICE DB 10,13,10,13
- DB '(C) Copyright 1988 G. Kent Cobb - All Rights Reserved$'
- ERROR_MESSAGE DB 10,13,10,13,'Cannot install profiler. Terminating.$'
-
- INT_NUMS DB PRINT_SCREEN_INTERRUPT
- DB VIDEO_INTERRUPT
- DB DISK_INTERRUPT
- DB COMM_INTERRUPT
- DB KEYBOARD_INTERRUPT
- DB PRINTER_INTERRUPT
- DB DOS_FUNC_INTERRUPT
- DB ABS_DISK_READ_INTERRUPT
- DB ABS_DISK_WRITE_INTERRUPT
-
- NEW_ISR_ADDRESS LABEL WORD
- DW OFFSET INTERRUPT_HANDLER1
- DW OFFSET INTERRUPT_HANDLER2
- DW OFFSET INTERRUPT_HANDLER3
- DW OFFSET INTERRUPT_HANDLER4
- DW OFFSET INTERRUPT_HANDLER5
- DW OFFSET INTERRUPT_HANDLER6
- DW OFFSET INTERRUPT_HANDLER7
- DW OFFSET INTERRUPT_HANDLER8
- DW OFFSET INTERRUPT_HANDLER9
-
- ;----------------------------------------------------------------------------;
- ; This stack is used during initialization only. ;
- ;----------------------------------------------------------------------------;
-
- OUR_STACK DD 100H DUP (0)
- END_STACK EQU $ ; SP is initialized to this value
-
- CODE_SEG ENDS
-
- END JUMP_TO_INIT
-
-