mirror of https://github.com/microsoft/MS-DOS.git
705 lines
21 KiB
NASM
705 lines
21 KiB
NASM
|
TITLE PROFIL - MS-DOS Profile program
|
|||
|
|
|||
|
;Profiler for MS-DOS 1.25 2.00
|
|||
|
;
|
|||
|
; Lots of stuff stolen from debug.
|
|||
|
; User provides # of paragraphs per bucket, program is cut up accordingly.
|
|||
|
; User also specifies clock interval
|
|||
|
|
|||
|
|
|||
|
;System calls
|
|||
|
PRINTBUF EQU 9
|
|||
|
SETDMA EQU 26
|
|||
|
CREATE EQU 22
|
|||
|
OPEN EQU 15
|
|||
|
CLOSE EQU 16
|
|||
|
GETBUF EQU 10
|
|||
|
BLKWRT EQU 40
|
|||
|
BLKRD EQU 39
|
|||
|
OUTCH EQU 2
|
|||
|
SETBASE EQU 38
|
|||
|
|
|||
|
FCB EQU 5CH
|
|||
|
BUFLEN EQU 80
|
|||
|
|
|||
|
; FCB offsets
|
|||
|
RR EQU 33
|
|||
|
RECLEN EQU 14
|
|||
|
FILELEN EQU 16
|
|||
|
|
|||
|
|
|||
|
;Segments in load order
|
|||
|
|
|||
|
CODE SEGMENT PUBLIC
|
|||
|
CODE ENDS
|
|||
|
|
|||
|
DATA SEGMENT BYTE
|
|||
|
DATA ENDS
|
|||
|
|
|||
|
INIT SEGMENT BYTE
|
|||
|
INIT ENDS
|
|||
|
|
|||
|
DG GROUP CODE,DATA,INIT
|
|||
|
|
|||
|
;The data segment
|
|||
|
|
|||
|
DATA SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
ENDMES DB 13,10,"Program terminated normally",13,10,"$"
|
|||
|
ABORTMES DB 13,10,"Program aborted",13,10,"$"
|
|||
|
TOOBIG DB "Program too big",13,10,"$"
|
|||
|
EXEBAD DB "EXE file bad",13,10,"$"
|
|||
|
|
|||
|
OUT_FCB LABEL WORD
|
|||
|
DB 0
|
|||
|
OUTNAME DB " PRF"
|
|||
|
DB 30 DUP(0)
|
|||
|
|
|||
|
DB 80H DUP(?)
|
|||
|
STACK LABEL WORD
|
|||
|
|
|||
|
BYTEBUF DB BUFLEN DUP(?) ;Processed input queue
|
|||
|
AXSAVE DW ? ;See interrupt routine
|
|||
|
BXSAVE DW ? ; " " "
|
|||
|
PROG_AREA DW ? ;Segment of program start
|
|||
|
|
|||
|
;EXE file header
|
|||
|
RUNVAR LABEL WORD
|
|||
|
RELPT DW ?
|
|||
|
LASTP LABEL WORD
|
|||
|
RELSEG DW ?
|
|||
|
PSIZE LABEL WORD
|
|||
|
PAGES DW ?
|
|||
|
RELCNT DW ?
|
|||
|
HEADSIZ DW ?
|
|||
|
DW ?
|
|||
|
LOADLOW DW ?
|
|||
|
PROG_SS LABEL WORD ;Program stack seg
|
|||
|
INITSS DW ?
|
|||
|
PROG_SP LABEL WORD ;Program SP
|
|||
|
INITSP DW ?
|
|||
|
DW ?
|
|||
|
PROG_ENTRY EQU THIS DWORD
|
|||
|
PROG_RA LABEL WORD ;Program start offset
|
|||
|
INITIP DW ?
|
|||
|
PROG_SA LABEL WORD ;Program start segment (may be different from PROG_AREA)
|
|||
|
INITCS DW ?
|
|||
|
RELTAB DW ?
|
|||
|
RUNVARSIZ EQU $-RUNVAR
|
|||
|
|
|||
|
EXEFILE DB 0 ;Flag to indicate EXE file
|
|||
|
DRV_VALID DW ? ;Init for AX register
|
|||
|
OUTPUT_DATA LABEL WORD ;Start of the profile data
|
|||
|
CLOCK_GRAIN DW ? ;Clock interval micro-seconds
|
|||
|
BUCKET_NUM DW ? ;Number of buckets
|
|||
|
BUCKET_SIZE DW ? ;Paragraphs per bucket
|
|||
|
PROG_LOW_PA DW ? ;Start of program (PARA #)
|
|||
|
PROG_HIGH_PA DW ? ;End of program (PARA #)
|
|||
|
DOS_PA DW ? ;IO-DOS PARA boundry
|
|||
|
HIT_IO DW 0 ;IO bucket
|
|||
|
HIT_DOS DW 0 ;DOS bucket
|
|||
|
HIT_HIGH DW 0 ;Above Program bucket
|
|||
|
NUM_DATA_WORDS EQU ($-OUTPUT_DATA)/2 ;Number of word items
|
|||
|
BUCKET LABEL WORD ;Bucket count area
|
|||
|
|
|||
|
;The following data will be overwritten when the buckets are initialized
|
|||
|
LINEBUF DB BUFLEN,1,0DH ;Raw input buffer
|
|||
|
DB BUFLEN DUP(?)
|
|||
|
|
|||
|
NOFILE DB "File not found",13,10,"$"
|
|||
|
OUTERR DB "Cannot open output file",13,10,"$"
|
|||
|
GRAIN_PROMPT DB "Sample time (micro-sec) >= 60 ? ","$"
|
|||
|
SIZE_PROMPT DB "Number of paragraphs (16 bytes) per bucket? ","$"
|
|||
|
PARAM_PROMPT DB "Parameters to program? ","$"
|
|||
|
DATA ENDS
|
|||
|
|
|||
|
;The resident code portion
|
|||
|
CODE SEGMENT PUBLIC
|
|||
|
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
|
|||
|
|
|||
|
;The clock interrupt routine
|
|||
|
PUBLIC CLK_INTER
|
|||
|
|
|||
|
;Stuff provided by external clock handler routine
|
|||
|
EXTRN CLOCKON:NEAR,CLOCKOFF:NEAR,LEAVE_INT:NEAR
|
|||
|
|
|||
|
ORG 100H
|
|||
|
START:
|
|||
|
CLD
|
|||
|
MOV SP,OFFSET DG:STACK ;Use internal stack
|
|||
|
CALL SETUP
|
|||
|
;The following setup stuff cannot be done in SETUP because we're probably
|
|||
|
; overwritting the INIT area
|
|||
|
MOV DX,[PROG_AREA]
|
|||
|
MOV AH,SETBASE
|
|||
|
INT 21H ;Set base for program
|
|||
|
MOV ES,[PROG_AREA]
|
|||
|
PUSH SI ;Points to BYTEBUF
|
|||
|
MOV DI,81H ;Set unformatted params
|
|||
|
COMTAIL:
|
|||
|
LODSB
|
|||
|
STOSB
|
|||
|
CMP AL,13
|
|||
|
JNZ COMTAIL
|
|||
|
SUB DI,82H ;Figure length
|
|||
|
XCHG AX,DI
|
|||
|
MOV BYTE PTR ES:[80H],AL
|
|||
|
POP SI
|
|||
|
MOV DI,FCB ;First param
|
|||
|
MOV AX,2901H
|
|||
|
INT 21H
|
|||
|
MOV BYTE PTR [DRV_VALID],AL
|
|||
|
MOV AX,2901H
|
|||
|
MOV DI,6CH ;Second param
|
|||
|
INT 21H
|
|||
|
MOV BYTE PTR [DRV_VALID+1],AL
|
|||
|
|
|||
|
MOV AX,ES ;Prog segment to AX
|
|||
|
MOV DX,[PROG_RA] ;Offset
|
|||
|
CMP [EXEFILE],1
|
|||
|
JZ EXELOAD ;EXE file
|
|||
|
JMP BINFIL ;Regular file (.COM)
|
|||
|
|
|||
|
EXELOAD:
|
|||
|
MOV AX,[HEADSIZ] ;Size of header in paragraphs
|
|||
|
ADD AX,31
|
|||
|
MOV CL,4
|
|||
|
ROL AX,CL ;Size in bytes
|
|||
|
MOV BX,AX
|
|||
|
AND AX,0FE00H
|
|||
|
AND BX,0FH
|
|||
|
MOV WORD PTR DS:[FCB+RR],AX ;Position in file of program
|
|||
|
MOV WORD PTR DS:[FCB+RR+2],BX ;Record size
|
|||
|
MOV DX,[PAGES] ;Size in 512 byte blocks
|
|||
|
DEC DX
|
|||
|
XCHG DH,DL
|
|||
|
ROL DX,1
|
|||
|
MOV DI,DX
|
|||
|
MOV SI,DX
|
|||
|
AND DI,0FE00H
|
|||
|
AND SI,1FFH
|
|||
|
SUB DI,AX
|
|||
|
SBB SI,BX
|
|||
|
MOV AX,[LASTP]
|
|||
|
OR AX,AX
|
|||
|
JNZ PARTP
|
|||
|
MOV AX,200H
|
|||
|
PARTP:
|
|||
|
ADD DI,AX
|
|||
|
ADC SI,0
|
|||
|
MOV AX,DI
|
|||
|
ADD AX,15
|
|||
|
AND AL,0F0H
|
|||
|
OR AX,SI
|
|||
|
MOV CL,4
|
|||
|
ROR AX,CL
|
|||
|
XCHG AX,CX
|
|||
|
MOV BX,[PROG_AREA]
|
|||
|
ADD BX,10H
|
|||
|
MOV AX,WORD PTR DS:[2]
|
|||
|
SUB AX,CX
|
|||
|
MOV DX,OFFSET DG:TOOBIG
|
|||
|
JB ERROR
|
|||
|
CMP BX,AX
|
|||
|
JA ERROR
|
|||
|
CMP [LOADLOW],-1
|
|||
|
JNZ LOADEXE
|
|||
|
XCHG AX,BX
|
|||
|
LOADEXE:
|
|||
|
MOV BP,AX
|
|||
|
XOR DX,DX
|
|||
|
CALL READ
|
|||
|
JC HAVEXE
|
|||
|
BADEXE:
|
|||
|
MOV DX,OFFSET DG:EXEBAD
|
|||
|
|
|||
|
ERROR:
|
|||
|
MOV AH,PRINTBUF ;Print the message in DX
|
|||
|
INT 21H
|
|||
|
INT 20H ;Exit
|
|||
|
|
|||
|
HAVEXE:
|
|||
|
MOV AX,[RELTAB] ;Get position of relocation table
|
|||
|
MOV WORD PTR DS:[FCB+RR],AX
|
|||
|
MOV WORD PTR DS:[FCB+RR+2],0
|
|||
|
MOV DX,OFFSET DG:RELPT ;Four byte buffer
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
CMP [RELCNT],0
|
|||
|
JZ NOREL
|
|||
|
RELOC:
|
|||
|
MOV AH,BLKRD
|
|||
|
MOV DX,FCB
|
|||
|
MOV CX,4
|
|||
|
INT 21H ;Read in one relocation pointer
|
|||
|
OR AL,AL
|
|||
|
JNZ BADEXE
|
|||
|
MOV DI,[RELPT] ;Pointer offset
|
|||
|
MOV AX,[RELSEG] ;pointer segment
|
|||
|
ADD AX,BP ;Bias with actual load segment
|
|||
|
MOV ES,AX
|
|||
|
ADD ES:[DI],BP ;Relocate
|
|||
|
DEC [RELCNT]
|
|||
|
JNZ RELOC
|
|||
|
|
|||
|
NOREL:
|
|||
|
ADD [INITSS],BP
|
|||
|
ADD [INITCS],BP
|
|||
|
JMP SHORT PROGGO
|
|||
|
|
|||
|
BINFIL:
|
|||
|
MOV WORD PTR DS:[FCB+RECLEN],1
|
|||
|
MOV SI,-1
|
|||
|
MOV DI,SI
|
|||
|
CALL READ
|
|||
|
MOV ES,[PROG_SA] ;Prog segment to ES
|
|||
|
MOV AX,WORD PTR ES:[6]
|
|||
|
MOV [PROG_SP],AX ;Default SP for non EXE files
|
|||
|
DEC AH
|
|||
|
MOV WORD PTR ES:[6],AX ;Fix size
|
|||
|
|
|||
|
PROGGO:
|
|||
|
PUSH DS
|
|||
|
MOV AX,[PROG_AREA]
|
|||
|
MOV DS,AX
|
|||
|
MOV DX,80H
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H ;Set default disk transfer address
|
|||
|
POP DS
|
|||
|
MOV BX,[BUCKET_NUM]
|
|||
|
SHL BX,1 ;Mult by 2 to get #bytes in bucket area
|
|||
|
CLEAR:
|
|||
|
MOV BUCKET[BX],0 ;Zero counts
|
|||
|
SUB BX,2
|
|||
|
JGE CLEAR
|
|||
|
MOV DX,[CLOCK_GRAIN]
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
CLI ;Don't collect data yet
|
|||
|
CALL CLOCKON ;Set the interrupt
|
|||
|
MOV SI,[PROG_RA]
|
|||
|
MOV DI,[PROG_AREA]
|
|||
|
MOV BX,[PROG_SS]
|
|||
|
MOV CX,[PROG_SP]
|
|||
|
MOV AX,[DRV_VALID]
|
|||
|
MOV DX,[PROG_SA]
|
|||
|
MOV SS,BX
|
|||
|
MOV SP,CX
|
|||
|
XOR CX,CX
|
|||
|
PUSH CX ;0 on prog stack
|
|||
|
PUSH DX
|
|||
|
PUSH SI
|
|||
|
MOV DS,DI ;Set up segments
|
|||
|
MOV ES,DI
|
|||
|
STI ;Start collecting data
|
|||
|
XXX PROC FAR
|
|||
|
RET ;Hop to program
|
|||
|
XXX ENDP
|
|||
|
|
|||
|
READ:
|
|||
|
; AX:DX is disk transfer address (segment:offset)
|
|||
|
; SI:DI is 32 bit length
|
|||
|
|
|||
|
RDLOOP:
|
|||
|
MOV BX,DX
|
|||
|
AND DX,000FH
|
|||
|
MOV CL,4
|
|||
|
SHR BX,CL
|
|||
|
ADD AX,BX
|
|||
|
PUSH AX
|
|||
|
PUSH DX
|
|||
|
PUSH DS
|
|||
|
MOV DS,AX
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
POP DS
|
|||
|
MOV DX,FCB
|
|||
|
MOV CX,0FFF0H ;Keep request in segment
|
|||
|
OR SI,SI ;Need > 64K?
|
|||
|
JNZ BIGRD
|
|||
|
MOV CX,DI ;Limit to amount requested
|
|||
|
BIGRD:
|
|||
|
MOV AH,BLKRD
|
|||
|
INT 21H
|
|||
|
SUB DI,CX ;Subtract off amount done
|
|||
|
SBB SI,0 ;Ripple carry
|
|||
|
CMP AL,1 ;EOF?
|
|||
|
POP DX
|
|||
|
POP AX ;Restore transfer address
|
|||
|
JZ RET10
|
|||
|
ADD DX,CX ;Bump transfer address by last read
|
|||
|
MOV BX,SI
|
|||
|
OR BX,DI ;Finished with request
|
|||
|
JNZ RDLOOP
|
|||
|
RET10: STC
|
|||
|
RET
|
|||
|
|
|||
|
|
|||
|
;Return here on termination or abort
|
|||
|
|
|||
|
TERMINATE:
|
|||
|
CLI ;Stop collecting data
|
|||
|
MOV DX,OFFSET DG:ENDMES
|
|||
|
JMP SHORT WRITEOUT
|
|||
|
ABORT:
|
|||
|
CLI ;Stop collecting data
|
|||
|
MOV DX,OFFSET DG:ABORTMES
|
|||
|
WRITEOUT:
|
|||
|
MOV AX,CS
|
|||
|
MOV DS,AX
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET DG:STACK ;Use internal stack
|
|||
|
PUSH DX
|
|||
|
CALL CLOCKOFF ;Restore original clock routine
|
|||
|
STI ;Back to normal clock
|
|||
|
POP DX
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H ;Apropriate termination message
|
|||
|
MOV [OUT_FCB+14],2 ;Word size records
|
|||
|
MOV DX,OFFSET DG:OUTPUT_DATA
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H ;Set the transfer address
|
|||
|
MOV CX,NUM_DATA_WORDS
|
|||
|
ADD CX,[BUCKET_NUM]
|
|||
|
MOV DX,OFFSET DG:OUT_FCB
|
|||
|
MOV AH,BLKWRT
|
|||
|
INT 21H ;Write out data
|
|||
|
MOV DX,OFFSET DG:OUT_FCB
|
|||
|
MOV AH,CLOSE
|
|||
|
INT 21H
|
|||
|
INT 20H ;Exit
|
|||
|
|
|||
|
|
|||
|
;The clock interrupt routine
|
|||
|
CLK_INTER PROC NEAR
|
|||
|
CLI
|
|||
|
PUSH DS
|
|||
|
PUSH CS
|
|||
|
POP DS ;Get profile segment
|
|||
|
MOV [AXSAVE],AX
|
|||
|
MOV [BXSAVE],BX
|
|||
|
POP AX ;old DS
|
|||
|
MOV BX,OFFSET DG:LEAVE_INT
|
|||
|
PUSH BX
|
|||
|
PUSH AX
|
|||
|
PUSH ES
|
|||
|
PUSH [AXSAVE]
|
|||
|
PUSH [BXSAVE]
|
|||
|
PUSH CX
|
|||
|
PUSH DX
|
|||
|
|
|||
|
|
|||
|
;Stack looks like this
|
|||
|
;
|
|||
|
; +18 OLDFLAGS
|
|||
|
; +16 OLDCS
|
|||
|
; +14 OLDIP
|
|||
|
; +12 RETURN TO LEAVE_INT
|
|||
|
; +10 OLDDS
|
|||
|
; +8 OLDES
|
|||
|
; +6 OLDAX
|
|||
|
; +4 OLDBX
|
|||
|
; +2 OLDCX
|
|||
|
;SP-> OLDDX
|
|||
|
|
|||
|
MOV BX,SP
|
|||
|
LES BX,DWORD PTR SS:[BX+14] ;Get CS:IP
|
|||
|
MOV AX,BX
|
|||
|
MOV CL,4
|
|||
|
SHR AX,CL
|
|||
|
MOV CX,ES
|
|||
|
ADD AX,CX ;Paragraph of CS:IP
|
|||
|
CMP AX,[DOS_PA] ;Below DOS?
|
|||
|
JB IOHIT
|
|||
|
CMP AX,[PROG_LOW_PA] ;Below program?
|
|||
|
JB DOSHIT
|
|||
|
CMP AX,[PROG_HIGH_PA] ;Above program?
|
|||
|
JAE MISSH
|
|||
|
|
|||
|
SUB AX,[PROG_LOW_PA] ;Paragraph offset
|
|||
|
XOR DX,DX
|
|||
|
|
|||
|
DIV [BUCKET_SIZE]
|
|||
|
MOV BX,AX
|
|||
|
SHL BX,1 ;Mult by 2 to get byte offset
|
|||
|
INC BUCKET[BX]
|
|||
|
JMP SHORT DONE
|
|||
|
|
|||
|
IOHIT:
|
|||
|
INC [HIT_IO]
|
|||
|
JMP SHORT DONE
|
|||
|
|
|||
|
DOSHIT:
|
|||
|
INC [HIT_DOS]
|
|||
|
JMP SHORT DONE
|
|||
|
|
|||
|
MISSH:
|
|||
|
INC [HIT_HIGH]
|
|||
|
|
|||
|
DONE:
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
POP BX
|
|||
|
POP AX
|
|||
|
POP ES
|
|||
|
POP DS
|
|||
|
STI
|
|||
|
RET ;To LEAVE_INT
|
|||
|
|
|||
|
CLK_INTER ENDP
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
|
|||
|
;The init segment contains code to process input parameters
|
|||
|
; It will be blasted as soon as the program to be run is read in
|
|||
|
; And/or the bucket area is initialized
|
|||
|
|
|||
|
INIT SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
|
|||
|
SETUP:
|
|||
|
MOV DX,FCB
|
|||
|
MOV AH,OPEN
|
|||
|
INT 21H ;Open program file
|
|||
|
AND AL,AL
|
|||
|
JZ OPENOK
|
|||
|
MOV DX,OFFSET DG:NOFILE
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
OPENOK:
|
|||
|
XOR BX,BX
|
|||
|
MOV WORD PTR DS:[FCB+RR],BX
|
|||
|
MOV WORD PTR DS:[FCB+RR+2],BX ;RR to 0
|
|||
|
MOV SI,FCB
|
|||
|
MOV DI,OFFSET DG:OUT_FCB
|
|||
|
MOV CX,4
|
|||
|
REP MOVSW
|
|||
|
MOVSB ;Transfer drive spec and file to output
|
|||
|
MOV DX,OFFSET DG:OUT_FCB
|
|||
|
MOV AH,CREATE
|
|||
|
INT 21H ;Try to create the output file
|
|||
|
AND AL,AL
|
|||
|
JZ GETSIZE
|
|||
|
MOV DX,OFFSET DG:OUTERR
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
GETSIZE: ;Get bucket size
|
|||
|
MOV DX,OFFSET DG:SIZE_PROMPT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
CALL INBUF
|
|||
|
CALL SCANB
|
|||
|
JZ GETSIZE ;SCANB went to CR
|
|||
|
XOR BX,BX
|
|||
|
INC BX ;Size >=1
|
|||
|
CALL GETNUM
|
|||
|
JC GETSIZE ;Bad number
|
|||
|
MOV [BUCKET_SIZE],DX
|
|||
|
|
|||
|
CMP WORD PTR DS:[FCB+9],5800H+"E" ;"EX"
|
|||
|
JNZ NOTEXE
|
|||
|
CMP BYTE PTR DS:[FCB+11],"E"
|
|||
|
JNZ NOTEXE
|
|||
|
|
|||
|
LOADEXEHEAD: ;Load the EXE header
|
|||
|
MOV [EXEFILE],1
|
|||
|
MOV DX,OFFSET DG:RUNVAR ;Read header in here
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
MOV CX,RUNVARSIZ
|
|||
|
MOV DX,FCB
|
|||
|
MOV WORD PTR DS:[FCB+RECLEN],1
|
|||
|
OR AL,AL
|
|||
|
MOV AH,BLKRD
|
|||
|
INT 21H
|
|||
|
CMP [RELPT],5A4DH ;Magic number
|
|||
|
JZ EXEOK
|
|||
|
JMP BADEXE
|
|||
|
EXEOK:
|
|||
|
MOV AX,[PAGES] ;Size of file in 512 byte blocks
|
|||
|
MOV CL,5
|
|||
|
SHL AX,CL ;Size in paragraphs
|
|||
|
JMP SHORT SETBUCKET
|
|||
|
|
|||
|
NOTEXE:
|
|||
|
MOV AX,WORD PTR DS:[FCB+FILELEN]
|
|||
|
MOV DX,WORD PTR DS:[FCB+FILELEN+2] ;Size of file in bytes DX:AX
|
|||
|
ADD AX,15
|
|||
|
ADC DX,0 ;Round to PARA
|
|||
|
MOV CL,4
|
|||
|
SHR AX,CL
|
|||
|
AND AX,0FFFH
|
|||
|
MOV CL,12
|
|||
|
SHL DX,CL
|
|||
|
AND DX,0F000H
|
|||
|
OR AX,DX ;Size in paragraphs to AX
|
|||
|
MOV [PROG_RA],100H ;Default offset
|
|||
|
|
|||
|
SETBUCKET:
|
|||
|
PUSH AX ;Save size
|
|||
|
XOR DX,DX
|
|||
|
DIV [BUCKET_SIZE]
|
|||
|
INC AX ;Round up
|
|||
|
MOV [BUCKET_NUM],AX
|
|||
|
MOV BX,OFFSET DG:BUCKET
|
|||
|
SHL AX,1 ;Number of bytes in bucket area
|
|||
|
ADD AX,BX ;Size of profil in bytes
|
|||
|
ADD AX,15 ;Round up to PARA boundry
|
|||
|
MOV CL,4
|
|||
|
SHR AX,CL ;Number of paragraphs in profil
|
|||
|
INC AX ;Insurance
|
|||
|
MOV BX,CS
|
|||
|
ADD AX,BX
|
|||
|
MOV [PROG_AREA],AX
|
|||
|
|
|||
|
CMP [EXEFILE],1
|
|||
|
JZ SETBOUNDS
|
|||
|
MOV AX,[PROG_AREA] ;Set up .COM segments
|
|||
|
MOV [PROG_SS],AX
|
|||
|
MOV [PROG_SA],AX
|
|||
|
|
|||
|
SETBOUNDS: ;Set the sample window
|
|||
|
MOV BX,10H ;Get start offset
|
|||
|
ADD BX,[PROG_AREA] ;PARA # of start
|
|||
|
MOV [PROG_LOW_PA],BX
|
|||
|
POP AX ;Recall size of PROG in paragraphs
|
|||
|
ADD BX,AX
|
|||
|
MOV [PROG_HIGH_PA],BX
|
|||
|
|
|||
|
SETDOS:
|
|||
|
XOR DX,DX
|
|||
|
MOV ES,DX ;look in interrupt area
|
|||
|
MOV DX,WORD PTR ES:[82H] ;From int #20
|
|||
|
MOV [DOS_PA],DX
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
|
|||
|
GETGRAIN: ;Get sample interval
|
|||
|
MOV DX,OFFSET DG:GRAIN_PROMPT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
CALL INBUF
|
|||
|
CALL SCANB
|
|||
|
JZ GETGRAIN ;SCANB went to CR
|
|||
|
MOV BX,60 ;Grain >=60
|
|||
|
CALL GETNUM
|
|||
|
JC GETGRAIN ;Bad number
|
|||
|
MOV [CLOCK_GRAIN],DX
|
|||
|
|
|||
|
MOV DX,OFFSET DG:PARAM_PROMPT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
CALL INBUF ;Get program parameters
|
|||
|
|
|||
|
MOV AX,2522H ;Set vector 22H
|
|||
|
MOV DX,OFFSET DG:TERMINATE
|
|||
|
INT 21H
|
|||
|
MOV AL,23H ;Set vector 23H
|
|||
|
MOV DX,OFFSET DG:ABORT
|
|||
|
INT 21H
|
|||
|
RET ;Back to resident code
|
|||
|
|
|||
|
GETNUM: ;Get a number, DS:SI points to buffer, carry set if bad
|
|||
|
XOR DX,DX
|
|||
|
MOV CL,0
|
|||
|
LODSB
|
|||
|
NUMLP:
|
|||
|
SUB AL,"0"
|
|||
|
JB NUMCHK
|
|||
|
CMP AL,9
|
|||
|
JA NUMCHK
|
|||
|
CMP DX,6553
|
|||
|
JAE BADNUM
|
|||
|
MOV CL,1
|
|||
|
PUSH BX
|
|||
|
MOV BX,DX
|
|||
|
SHL DX,1
|
|||
|
SHL DX,1
|
|||
|
ADD DX,BX
|
|||
|
SHL DX,1
|
|||
|
CBW
|
|||
|
POP BX
|
|||
|
ADD DX,AX
|
|||
|
LODSB
|
|||
|
JMP NUMLP
|
|||
|
NUMCHK:
|
|||
|
CMP CL,0
|
|||
|
JZ BADNUM
|
|||
|
CMP BX,DX
|
|||
|
JA BADNUM
|
|||
|
CLC
|
|||
|
RET
|
|||
|
BADNUM:
|
|||
|
STC
|
|||
|
RET
|
|||
|
|
|||
|
INBUF: ;Read in from console, SI points to start on exit
|
|||
|
MOV AH,GETBUF
|
|||
|
MOV DX,OFFSET DG:LINEBUF
|
|||
|
INT 21H
|
|||
|
MOV SI,2 + OFFSET DG:LINEBUF
|
|||
|
MOV DI,OFFSET DG:BYTEBUF
|
|||
|
CASECHK:
|
|||
|
LODSB
|
|||
|
CMP AL,'a'
|
|||
|
JB NOCONV
|
|||
|
CMP AL,'z'
|
|||
|
JA NOCONV
|
|||
|
ADD AL,"A"-"a" ;Convert to upper case
|
|||
|
NOCONV:
|
|||
|
STOSB
|
|||
|
CMP AL,13
|
|||
|
JZ INDONE
|
|||
|
CMP AL,'"'
|
|||
|
JNZ QUOTSCAN
|
|||
|
CMP AL,"'"
|
|||
|
JNZ CASECHK
|
|||
|
QUOTSCAN:
|
|||
|
MOV AH,AL
|
|||
|
KILLSTR:
|
|||
|
LODSB
|
|||
|
STOSB
|
|||
|
CMP AL,13
|
|||
|
JZ INDONE
|
|||
|
CMP AL,AH
|
|||
|
JNZ KILLSTR
|
|||
|
JMP SHORT CASECHK
|
|||
|
|
|||
|
INDONE:
|
|||
|
MOV SI,OFFSET DG:BYTEBUF
|
|||
|
|
|||
|
;Output CR/LF
|
|||
|
|
|||
|
CRLF:
|
|||
|
MOV AL,13
|
|||
|
CALL OUT
|
|||
|
MOV AL,10
|
|||
|
|
|||
|
OUT:
|
|||
|
PUSH AX
|
|||
|
PUSH DX
|
|||
|
AND AL,7FH
|
|||
|
XCHG AX,DX
|
|||
|
MOV AH,OUTCH
|
|||
|
INT 21H
|
|||
|
POP DX
|
|||
|
POP AX
|
|||
|
RET
|
|||
|
|
|||
|
SCANB: ;Scan to first non-blank
|
|||
|
PUSH AX
|
|||
|
SCANNEXT:
|
|||
|
LODSB
|
|||
|
CMP AL," "
|
|||
|
JZ SCANNEXT
|
|||
|
CMP AL,9
|
|||
|
JZ SCANNEXT
|
|||
|
DEC SI
|
|||
|
POP AX
|
|||
|
EOLCHK:
|
|||
|
CMP BYTE PTR[SI],13
|
|||
|
RET
|
|||
|
|
|||
|
INIT ENDS
|
|||
|
END START
|
|||
|
|