home *** CD-ROM | disk | FTP | other *** search
- PAGE,132
- ;from PC Tech Journal, NOV/86, Vol4 No11, p120 "Execution Profiler"
- ;
- ;User changeable constants to reconfigure profiler
- ;
- ; Number of bytes in data table (F000 = 60K)
- Table_Size EQU 0F000H
- ; Number of ticks between jumps to original clock interrupt handler
- ; = Clock Speedup Factor
- NUMBER_OF_TICKS EQU 1
- ;
- ;Other constants
- ;
- ; Maximum value of countdown for Timer 0 interrupt
- MAX_TIMER_COUNT EQU 0FFFFH
- ;
- ; New value of countdown for Timer 0 interrupt
- New_Timer_Count EQU MAX_TIMER_COUNT / NUMBER_OF_TICKS
- ;
- ;
- PSP SEGMENT PUBLIC
- ASSUME CS:PSP, DS:PSP, ES:PSP, SS:PSP
- ORG 100H ;COM file
- ;
- ; Profiler kernel
- ;
- ; 1. Program executes file 'subject.com' which may be a com or exe file.
- ; Use a batch file to copy subject file to 'subject.com'
- ;
- ; 2. Run with 'prf fn1 fn2' where 'fn1' and 'fn2' are the parameters
- ; you would have typed if you had been running the subject code by
- ; itself. This allows copying the formatted file info from the
- ; profiler's PSP into the PSP for the subject code.
- ;
- PRF PROC FAR
- MOV SP, OFFSET END_STACK ;set top of stack to internal area
- CALL FREE_MEM
- CALL REPLACE_TIMER
- CALL EXEC_SUBJECT
- CALL RESTORE_TIMER
- CALL EXEC_PRINT
- INT 20H
- PRF ENDP
- ; ==================================
- ; Subroutines
- ;
- ;
- ; Return unused memory to DOS
- ;
- FREE_MEM PROC NEAR
- MOV BX,OFFSET EOM ; offset top of used memory
- MOV CL,4
- SHR BX,CL ; divide by 16 to get number of paragraphs
- ADD BX,01 ; to take care of any remainder
- MOV AH,4AH ; modify allocated memory
- INT 21H
- JNC SUCCESS ; carry flag is set if error
- MOV AH,09 ; DOS fnctn print string
- MOV DX,OFFSET MEM_ERR_STRNG
- INT 21H
- INT 20H ; terminate after printing error message
- SUCCESS: RET
- FREE_MEM ENDP
- ; -------------------------------
- ; Run subject program under profiler
- ;
- EXEC_SUBJECT PROC NEAR
- MOV AX,CS ;to set seg registers
- MOV DS,AX ;DS:DX points to ASCIIZ string with
- MOV DX,OFFSET SUBJECT_NAME ;name of file to execute
- MOV ES,AX ;es:bx points to parameter block
- MOV BX,OFFSET EXEC_PARAMS
- MOV CX,CS:[2CH] ;set segment address
- MOV ENVIRON_SEG,CX ;of passed environment
- MOV COMMND_OFS,80H ;set offset and segment
- MOV COMMND_SEG,CS ;of passed command line
- MOV FCB1_OFS,5CH ;set offset and segment
- MOV FCB1_SEG,CS ;of unopened FCB1
- MOV FCB2_OFS,6CH ;set offset and segment
- MOV FCB2_SEG,CS ;of unopened FCB@
- MOV AX,4B00H ;DOS fnctn Load/Execute
- MOV ACCUM_FLAG, 1 ;turn on address accumulation flag
- MOV SAV_SP,SP ;save stack pointer
- INT 21H
- MOV AX,CS ;restore segment registers and stack
- MOV ES,AX
- MOV DS,AX
- MOV SS,AX
- MOV SP,SAV_SP
- MOV ACCUM_FLAG, 0 ;and turn off address accumulation flag
- RET
- EXEC_SUBJECT ENDP
- ; -----------------------------------
- ;
- ; Run program to display profiler output
- ;
- EXEC_PRINT PROC NEAR
- MOV AX,CS
- MOV ES,AX
- MOV DS,AX ;DS:DX point to ASCIIZ string with name of
- MOV SS,AX ;file to execute
- MOV DS,AX
- MOV DX,OFFSET PRINT_NAME
- ; move segment and offset of data into words 0-3 of FCB1, CS:5CH
- MOV AX,OFFSET DATA_TABLE
- MOV BX,5CH ;offset into code seg of FCB1
- MOV CS:[BX],AX ;move offset into into FCB1
- MOV AX,CS
- MOV CS:[BX+2],AX ;move CS into FCB1
- ; divide table offset by four to get number of samples
- MOV CL,2
- SHR TABLE_OFS,CL ;shift to divide
- MOV ES,AX ;ES:BX points to parameter block
- MOV BX,OFFSET EXEC_PARAMS
- MOV CX,CS:[2CH] ;turn off address
- MOV ENVIRON_SEG,CS ;accumulation flag.
- MOV COMMND_OFS,80H ;set offset and segment
- MOV COMMND_SEG,CS ;of passed command line.
- MOV FCB1_OFS,5CH ;set offset and segment
- MOV FCB1_SEG,CS ;to unopened FCB1
- MOV FCB2_OFS,6CH ;and to FCB2
- MOV FCB2_SEG,CS
- MOV SAV_SP,SP ;save stack pointer
- MOV AX,4B00H
- INT 21H ;execute named program
- MOV AX,CS
- MOV DS,AX ;restore segment registers
- MOV ES,AX
- MOV SS,AX
- MOV SP,SAV_SP ;and stack pointer
- RET
- EXEC_PRINT ENDP
- ; --------------------------------------
- ;
- ; Restore original INT 8 and timer 0 countdown to power-up value
- ;
- RESTORE_TIMER PROC NEAR
- CLI
- ; restore INT 8
- MOV AX,0
- MOV DS,AX
- MOV AX,CS:OLD_OFS
- MOV DS:[20H],AX ;puts old offset back into int table
- MOV AX,CS:OLD_SEG
- MOV DS:[22H],AX ;puts old segment back
- ; restore timer 0 countdown to power-up value
- MOV AL,36H ;timer 0, mode 3 (send lsb, msb)
- OUT 43H,AL ;write current mode control word to timer
- MOV AL,0 ;lsb and msb of 0
- OUT 40H,AL ;write lsb to timer 0
- OUT 40H,AL ;write msb to timer 0
- STI
- RET
- RESTORE_TIMER ENDP
- ; ---------------------------------------
- ;
- ; Replaces old timer interrupt. accumulates data if ACCUM_FLAG is set &
- ; jumps to old INT 8 if timing is appropriate.
- NEW_TIMER PROC NEAR
- CMP CS:ACCUM_FLAG,0
- JE DO_OLD_INT8? ;skip accumulate if 0
- CALL ACCUMULATE
- DO_OLD_INT8?:
- INC CS:TIMER_COUNT ;increment counter
- CMP CS:TIMER_COUNT, NUMBER_OF_TICKS ;do it this tick?
- JNE SKIP_OLD_INT8 ;skip INT 8 if not time
- MOV CS:TIMER_COUNT,0 ;reset counter to 0
- JMP CS:DWORD PTR OLD_INT8
- SKIP_OLD_INT8:
- PUSH AX
- MOV AL,20H ;end of interrupt code
- OUT 20H,AL ;send eoi to 8259
- POP AX
- IRET
- NEW_TIMER ENDP
- ;
- ; accumulate data at clock interrupt
- ACCUMULATE PROC NEAR
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH BP
- ; check for table overflow
- MOV AX,CS:MAX_OFS
- CMP CS:TABLE_OFS, AX ;have we reached end of table?
- JAE END_ACCUM ;if so, skip data accumulation
- ; accumulate samples
- MOV BX,CS:TABLE_OFS
- MOV BP,SP
- MOV AX,SS:[BP+10] ;load AX with interrupted IP
- MOV CS:WORD PTR DATA_TABLE[BX],AX ;save IP
- MOV AX,SS:[BP+12] ;load AX with interrupted CS
- MOV CS:WORD PTR DATA_TABLE[BX+2],AX ;save CS
- ADD CS:TABLE_OFS, 4 ;increment offset into table
- END_ACCUM:
- POP BP
- POP CX
- POP BX
- POP AX
- RET
- ACCUMULATE ENDP
- ; ----------------------------------
- ;
- ; Replace existing timer 0 countdown and existing INT 8
- ;
- REPLACE_TIMER PROC NEAR
- PUSH DS
- CLI ;disable maskable interrupts
- ; change timer 0 countdown to (maybe) speed up timer
- MOV AL,36H ;timer 0, mode 3, will send lsb, msb
- OUT 43H,AL ;write mode control word to timer
- MOV BX,NEW_TIMER_COUNT
- MOV AL,BL ;lsb of NEW_TIMER_COUNT
- OUT 40H,AL ;write lsb to timer 0
- MOV AL,BH ;msb of NEW_TIMER_COUNT
- OUT 40H,AL ;write msb to timer 0
- ; replace existing INT 8
- XOR AX,AX
- MOV DS,AX ;seg for interrupt vectors (0)
- MOV AX,DS:[20H] ;offset of INT 8 vector to AX
- MOV CS:OLD_OFS,AX ;and save it
- MOV AX,DS:[22H] ;segment of INT 8 vector to AX
- MOV CS:OLD_SEG,AX ;and save it
- MOV DS:[20H],OFFSET NEW_TIMER ;implant new offset
- MOV DS:[22H],CS ;implant new segment
- STI ;enable maskable interrupts
- POP DS
- RET
- REPLACE_TIMER ENDP
- ; -------------------------------------
- ; Data area
- ;
- SUBJECT_NAME DB 'SUBJECT.COM' ;ASCIIZ name of subject
- DB 0 ;ASCIIZ terminator
- MEM_ERR_STRNG DB 'Error shrinking memory - Profile ends$'
- EXEC_PARAMS EQU $ ;parameters passed
- ENVIRON_SEG DW ? ;to executed programs
- COMMND_OFS DW ?
- COMMND_SEG DW ?
- FCB1_OFS DW ?
- FCB1_SEG DW ?
- FCB2_OFS DW ?
- FCB2_SEG DW ?
- SAV_SP DW ?
- PRINT_NAME DB 'LISTPRF.COM'
- DB 0 ;ASCIIZ terminator
- TIMER_COUNT DW 0
- ACCUM_FLAG DW 0
- OLD_INT8 EQU $ ;address old timer interrupt
- OLD_OFS DW ?
- OLD_SEG DW ?
- OUR_STACK DD 100H DUP(0) ;space for our stack
- END_STACK EQU $ ;set SP to this offset
- MAX_OFS DW Table_Size ;max offset from beginning of data table
- TABLE_OFS DW ? ;current offset into data table
- DATA_TABLE DB Table_Size DUP(0)
- EOM EQU $
- PSP ENDS
- END PRF
-
-