home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
start.asm
< prev
next >
Wrap
Assembly Source File
|
1988-06-02
|
24KB
|
938 lines
PAGE ,80
;
TITLE * START.ASM *
SUBTTL Program to start processes at a predetermined time.
;
; CREATED 06-DEC-85 :RICHARD B JOHNSON
;
IF1
%OUT [PASS1]
ELSE
%OUT [PASS2]
ENDIF
;
; Misc equates.
;
CR EQU 0DH
LF EQU 0AH
MS_DOS EQU 21H ;SYSTEM
CLK EQU 1CH ;TIMER VECTOR
CLX EQU 08H ;BEGINNING OF TIMER VECTOR
INT_BASE EQU 20H ;INTERRUPT CONTROLLER
VID_ROM EQU 10H ;VIDEO ROM
K EQU 1024
K16 EQU 16 * K
CMD_BUF EQU 80H ;COMMAND LINE
RAM EQU 12H ;GET AVAILABLE RAM
MAX_HRS EQU 23
MAX_MIN EQU 59
MAX_SEC EQU MAX_MIN
EQUIP EQU 410H ;EQUIPMENT FLAG
BWSEG EQU 0B000H ;SEGMENT FOR BLACK/WHITR
COSEG EQU 0B800H ;SEGMENT FOR COLOR
;
;
PSEG SEGMENT
ASSUME CS:PSEG,SS:PSEG,DS:PSEG,ES:NOTHING
ORG 100H
MAIN PROC NEAR
JMP INIT
DB 'Copyright (C) 1985 Richard B. Johnson. '
DB 'All rights reserved. '
PRP0 DB CR,LF,'Process $'
PRP1 DB CR,LF,'will start at '
HH DB '00:'
MM DB '00:'
SX DB '00. If not correct, hit any key.... $'
PRP2 DB ' aborted.',CR,LF,'$'
PRP3 DB ' loaded.',CR,LF,'$'
PRP4 DB CR,LF,'Usage:'
DB CR,LF,'START HH:MM:SS \PATH\RUNFILE COMMAND STRING'
DB CR,LF,LF,'Examples:'
DB CR,LF,'START 23:55:00 C:\DOS\BACKUP.BAT TODAYS FILES'
DB CR,LF,'START 12:00:00 \SETCLOCK'
DB CR,LF,'START 15:00:00 COPY *.DAT E:'
DB CR,LF,'$'
PRP5: DB CR,LF,'The time entered must be LATER than the present '
DB 'time!',CR,LF,'$'
;
BEEP DB 7,'Your process will resume in a moment.'
DB CR,LF,'$'
;
ERRW DB CR,LF,'Not enough disk space to save the screen'
DB CR,LF,'(need 16k).$'
;
FILE1 DB '\SCREEN.TMP',0
FILEN EQU $ - FILE1
FILE2 DB ' ',0
HANDLE DW ?
;
CNT DB 182 ;LOCAL CLOCK TICK COUNT
SEC DB ? ;LOCAL CLOCK SECONDS
MIN DB ? ;LOCAL CLOCK MINUTES
HRS DB ? ;LOCAL CLOCK HOURS
SAV_SEC DB ? ;COMMAND STRING SECS (BINARY)
SAV_MIN DB ? ;COMMAND STRING MINS (BINARY)
SAV_HRS DB ? ;COMMAND STRING HRS (BINARY)
SS_SAV DW ? ;USER'S STACK SEGMENT
SP_SAV DW ? ;USER'S STACK POINTER
COMMAND DB '\COMMAND.COM',0
;
BLOCK DW 0 ;PARAMETER BLOCK FOR EXEC
DW CMD_BUF ;DEFALUT BUFFER
BP_1 DW ? ;CS WRITTEN HERE
DW 5CH ;DEFAULT FCB
BP_2 DW ? ;CS WRITTEN HERE
DW 6CH ;OTHER FCB
BP_3 DW ? ;CS WRITTEN HERE
;
DTA_SEG DW ? ;USER'S DTA (SEGMENT)
DTA_OFF DW ? ;USER'S DTA (OFFSET)
SSP_SAV DW ? ;OUR STACK POINTER
SAV_SEG DW ? ;OLD INTERRUPT SEGMENT
SAV_OFF DW ? ;OLD INTERRUPT OFFSET
CUR_SAV DW ? ;CURSOR SAVE
CUR_TYP DW ? ;CURSOR TYPE
CUR_PGE DB ? ;CURRENT PAGE
OLD_CLK LABEL DWORD ;OLD TIMER VECTOR
IP_CLK DW ? ;IP FOR OLD CLOCK
CS_CLK DW ? ;CS FOR OLD CLOCK
OLD_CLX LABEL DWORD ;START OF CLOCK VECT
IP_CLX DW ? ;IP FOR START
CS_CLX DW ? ;CS FOR START
CRT_FLG LABEL DWORD ;CRITICAL FLAG (DOS)
DOS_FLG DW ? ;CRITICAL FLAG ADDRESS
DW ?
SEGMNT DW ? ;VIDEO SEGMENT
HERE DB 0 ;REENTRY FLAG
DISK DB ? ;CURRENT DISK
DIRZ DB '\'
DIRECT DB 64 DUP (?) ;CURRENT DIRECTORY
;
INFORM DB ' /C '
BUFFER DB ' ' ;THE SPACE
ASC_HRS DB 'HH:' ;HOURS IN ASCII
ASC_MIN DB 'MM:' ;MINUTES IN ASCII
NEW_CMD EQU $ - 2 ;NEW COMMAND LINE
NEW_TXT EQU NEW_CMD + 1 ;WHERE TEXT STARTS
ASC_SEC DB 'SS' ;SECONDS IN ASCII
DELIM DB ' ' ;NORMAL SPACE
DB 64 DUP (?) ;REST OF COMMAND LINE
LINE DB CR,LF,'Batch '
TIME DB '00:00:00 '
DATE DB '00-JAN-00 '
LEN EQU $ - LINE
LINEBUF DB 64 DUP (0)
MONTH DB 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'
LOGF DB '\BATCH.LOG',0 ;PROCESS LOG FILE
LOGCHAN DW ?
BYTES DW ?
;
EVEN
DB 32 DUP ('STACK ')
STK_TOP LABEL WORD
;
INIT: MOV AX,CS
MOV WORD PTR [BP_1],AX ;FOR 'LOAD AND EXECUTE'
MOV WORD PTR [BP_2],AX
MOV WORD PTR [BP_3],AX
CALL SET_TIM ;SET PRIVATE TIME
;
; Check for graphics board
;
PUSH DS ;SAVE DATA SEG
XOR AX,AX ;ZERO IT
MOV DS,AX
MOV AL,BYTE PTR DS:[EQUIP] ;GET EQUIPMENT FLAG
POP DS ;RESTORE DATA SEGMENT
AND AL,00110000B ;MASK TRASH
MOV WORD PTR [SEGMNT],BWSEG ;ASSUME SEGMENT FOR B/W
CMP AL,00110000B ;IS IT BLACK AND WHITE?
JZ SEG_OK ;YES
MOV WORD PTR [SEGMNT],COSEG ;MUST BE COLOR
;
SEG_OK: CALL PARSE ;PARSE COMMAND LINE
JC FINIS ;BAD COMMAND LINE
CALL GET_FLAG ;SET UP CRITICAL PROCESS FLAG
CALL SET_INT ;SET UP INTERRUPTS
CALL SET_TIM ;SET TIME AGAIN
CALL KEEP3K
KEEP: MOV AX,3100H ;KEEP PROCESS FUNCTION
INT MS_DOS
HLT ;IN CASE SOMETHING'S BUSTED
FINIS: MOV AX,4C00H ;TERMINATE PROCESS
INT MS_DOS
MAIN ENDP
;
CLK_INT PROC FAR
ASSUME CS:PSEG,SS:PSEG,DS:PSEG,ES:NOTHING
PUSH AX ;SAVE
PUSH DS ;AND DS
PUSH CS ;COPY CODE SEGMENT
POP DS ;INTO DATA SEG
;
; We get interupted 18.2 times per second.
; Routine below produces 1 second 'Ticks' by
; dividing by 18.2 (honest). Subtracts 10 from 182
; each interupt and adds the remainder to 182 for
; the next run through the loop. Result is an AVERAGE
; division by 18.2.
CMP BYTE PTR [CNT],0FFH ;FLAG SHOWS THAT WE TIMED OUT
JZ BYPASS ;ALREADY TIMED OUT
SUB BYTE PTR [CNT],10 ;RUNNING COUNT
JNC BYPASS ;NO CARRY YET
ADD BYTE PTR [CNT],182 ;CUTE EH?
;
; Simple 24 hour clock counter follows.
;
INC BYTE PTR [SEC] ;BUMP SECONDS COUNTER
CMP BYTE PTR [SEC],60 ;ARE WE THERE YET?
JNZ TIM_OK ;NOPE
MOV BYTE PTR [SEC],0 ;YES, ZERO SECONDS AND ....
INC BYTE PTR [MIN] ;BUMP MINUTES
CMP BYTE PTR [MIN],60 ;ARE WE THERE YET?
JNZ TIM_OK ;NOPE
MOV BYTE PTR [MIN],0 ;YES, ZERO MINUTES AND.... ETC
INC BYTE PTR [HRS]
CMP BYTE PTR [HRS],24
JNZ TIM_OK
MOV BYTE PTR [HRS],0
;
; Check new time against saved time from command line.
;
TIM_OK: MOV AL,BYTE PTR [HRS] ;GET HOURS
CMP AL,BYTE PTR [SAV_HRS] ;SAME AS SAVED?
JNZ BYPASS ;NO
MOV AL,BYTE PTR [MIN] ;GET MINUTES
CMP AL,BYTE PTR [SAV_MIN] ;SAME AS SAVED?
JNZ BYPASS ;NO
MOV AL,BYTE PTR [SEC] ;GET SECONDS
CMP AL,BYTE PTR [SAV_SEC] ;SAME AS SAVED?
JNZ BYPASS ;NO
MOV BYTE PTR [CNT],0FFH ;SET FLAG (WE ARE TIMED OUT)
BYPASS: POP DS ;OLD DATA SEG
POP AX ;AND AX
JMP DWORD PTR CS:[OLD_CLK] ;CHAIN TO NEXT (IF ANY)
CLK_INT ENDP
;
; This is the second clock interrupt vector.
;
CLX_INT PROC FAR
CMP BYTE PTR CS:[HERE],0 ;SEE IF REENTRY IS OCCURING
JNZ HOME ;YES, DON'T ALLOW REENTRY
CMP BYTE PTR CS:[CNT],0FFH ;SEE IF WE TIMED OUT
JNZ HOME ;NO, NOT YET
;
; Check to see if we interrupted something important.
;
PUSH BX
PUSH DS
LDS BX,DWORD PTR CS:[CRT_FLG] ;GET CRITICAL FLAG
CMP BYTE PTR DS:[BX],0
POP DS
POP BX
JZ TIMOUT ;OK TO MAKE DOS CALLS
;
DONE: MOV BYTE PTR CS:[HERE],0 ;RESTORE REENTRY FLAG
HOME: JMP DWORD PTR CS:[OLD_CLX] ;CONTINUE
;
; Coast is clear, save stack and continue.
;
TIMOUT: MOV BYTE PTR CS:[HERE],0FFH ;SET ENTRY FLAG
PUSH AX ;SAVE USER'S
PUSH DS ;AND DS
PUSH CS ;COPY CODE SEGMENT
POP DS ;INTO DATA SEG
CLI
MOV WORD PTR [SS_SAV],SS ;SAVE IT
MOV WORD PTR [SP_SAV],SP ;SAVE STACK POINTER
MOV AX,CS ;GET CODE SEG
MOV SS,AX ;INTO STACK SEG
MOV SP,OFFSET STK_TOP ;LOCAL STACK
;
PUSH BX ;SAVE EVERYTHING IN LOCAL STACK
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH BP
PUSH ES
MOV ES,AX ;CODE SEGMENT INTO EXTRA SEG
;
; Run the program
;
CODE PROC NEAR
CALL RES_INT ;RESTORE OLD INTERRUPT VECTORS
STI ;OK TO INTERRUPT
CALL RES_HRD ;RESET HARDWARE CONTROLLER
CALL SAV_SCR ;SAVE THE USER'S SCREEN
CALL TELL ;TELL USER WHAT WE'RE DOING
CALL LOG ;LOG TO DISK
CALL SAV_DIR ;SAVE CURRENT DIRECTORY
CALL SAV_DTA ;SAVE USERS DATA AREA
CALL SET_DTA ;SET UP LOCAL DATA AREA
CALL GET_MEM ;GET MORE MEMORY (dummy)
JC NOFREE ;NOTHING AVAILABLE
MOV ES,AX ;NEW SEGMENT ADDRESS OF AVAILABLE MEM
NOFREE: CALL KEEP3K ;RESTORE TO POOL
CALL RUN_PG ;LOAD/EXECUTE COMMAND.COM
CALL RES_DTA ;RESTORE USERS DATA TRANSFER AREA
CALL RES_DIR ;RESTORE CURRENT DIRECTORY
CALL RES_SCR ;RESTORE USER'S SCREEN
CALL KEEP0K ;GIVE UP ALL MEMORY
CODE ENDP
;
; Return to user program.
;
POP ES ;RESTORE USER'S REGISTERS
POP BP ;SAVED IN LOCAL STACK
POP SI
POP DI
POP DX
POP CX
POP BX
;
CLI
MOV SS,WORD PTR [SS_SAV] ;GET SAVED STACK SEG
MOV SP,WORD PTR [SP_SAV] ;GET OLD STACK POINTER
POP DS ;RESTORE REGISTERS FROM USER'S STACK
POP AX
STI ;ALLOW INTERRUPTS
JMP DONE ;CONTINUE
CLX_INT ENDP
;
GET_MEM PROC NEAR
MOV BX,40000 ;ASK FOR EVERYTHING IN THE COMPUTER
MOV AH,4AH
INT MS_DOS
RET
GET_MEM ENDP
;
SET_TIM PROC NEAR
MOV AH,2CH ;SET PRIVATE TIME
INT MS_DOS
MOV BYTE PTR [HRS],CH ;SAVE TIME IN PRIVATE CLOCK
MOV BYTE PTR [MIN],CL
MOV BYTE PTR [SEC],DH
RET
SET_TIM ENDP
;
SET_INT PROC NEAR
CLI
CLD ;FOREWARD
PUSH DS ;SAVE SEGMENT
XOR AX,AX ;GET OLD INTERRUPT VECTOR
MOV DS,AX ;FIRST SEGMENT IN MEMORY
MOV SI,(CLK * 4) ;INTERRUPT ADDRESS
LODSW ;GET OFFSET
MOV WORD PTR CS:[IP_CLK],AX ;SAVE IN OUR CODE SEGMENT DS IS BUSY
LODSW ;GET SEGMENT
MOV WORD PTR CS:[CS_CLK],AX ;SAVE THAT TOO
;
MOV SI,(CLX * 4) ;INTERRUPT ADDRESS
LODSW ;GET OFFSET
MOV WORD PTR CS:[IP_CLX],AX ;SAVE IN OUR CODE SEGMENT DS IS BUSY
LODSW ;GET SEGMENT
MOV WORD PTR CS:[CS_CLX],AX ;SAVE THAT TOO
POP DS ;RESTORE OUR DATA SEG
;
PUSH ES ;SAVE SEGMENT
XOR AX,AX ;ZERO
MOV ES,AX ;ZERO THE SEGMENT
MOV DI,(CLK * 4) ;GET INTERRUPT ADDRESS
MOV AX,OFFSET CLK_INT ;GET PROGRAM COUNTER
STOSW ;PATCH
MOV AX,CS ;GET CODE SEGMENT
STOSW
;
MOV DI,(CLX * 4) ;GET INTERRUPT ADDRESS
MOV AX,OFFSET CLX_INT ;GET PROGRAM COUNTER
STOSW ;PATCH
MOV AX,CS ;GET CODE SEGMENT
STOSW
POP ES
STI
RET
SET_INT ENDP
;
; Restore old clock vector(s).
;
RES_INT PROC NEAR
CLD ;FOREWARD
CLI ;NO INTERRUPTS
PUSH ES ;SAVE SEGMENT
XOR AX,AX ;ZERO
MOV ES,AX ;ZERO THE SEGMENT
MOV DI,(CLK * 4) ;GET INTERRUPT ADDRESS
MOV AX,WORD PTR [IP_CLK] ;GET PROGRAM COUNTER
STOSW ;PATCH
MOV AX,WORD PTR [CS_CLK] ;GET CODE SEGMENT
STOSW
;
MOV DI,(CLX * 4) ;GET INTERRUPT ADDRESS
MOV AX,WORD PTR [IP_CLX] ;GET PROGRAM COUNTER
STOSW ;PATCH
MOV AX,WORD PTR [CS_CLX] ;GET CODE SEGMENT
STOSW
;
POP ES ;RESTORE SEGMENT
STI ;ALLOW INTERRUPTS
RET
RES_INT ENDP
;
GET_FLAG PROC NEAR ;GET CRITICAL DOS FLAG
PUSH ES ;WILL RETURN IN ES SO SAVE
MOV AH,34H ;FUNCTION
INT MS_DOS ;DO IT
MOV WORD PTR [DOS_FLG],BX ;SAVE IP
MOV WORD PTR DOS_FLG[2],ES ;SAVE CS
POP ES ;RESTORE EXTRA
RET
GET_FLAG ENDP
;
PARSE PROC NEAR
MOV SI,CMD_BUF ;POINT TO THE STRING
LODSB ;GET BYTE FROM BUFFER
OR AL,AL
JZ BAD ;NOTHING TYPED
CBW
MOV CX,AX ;USE AS COUNT
CALL CASE ;FORCE TO UPPER CASE
MOV DI,SI ;COPY FOR COMPARE
MOV AL,' ' ;LOOK FOR A SPACE
REPZ SCASB ;GET BY SPACES
JCXZ BAD ;NO SPACE
MOV AL,':' ;DELIMITER _AFTER_ CHARACTER
CALL GET_CHR ;GET CHARS, CONV TO BINARY
JC BAD ;NO GOOD
CMP AL,MAX_HRS ;WITHIN RANGE?
JG BAD ;NOPE
MOV BYTE PTR [SAV_HRS],AL ;SAVE GOOD BINARY
MOV AL,':' ;NEXT DELIMITER
CALL GET_CHR ;GET CHARACTER(S)
JC BAD ;BAD CHARACTER(S)
CMP AL,MAX_MIN ;WITHIN RANGE?
JG BAD ;NOPE
MOV BYTE PTR [SAV_MIN],AL ;SAVE GOOD BINARY
MOV AL,' ' ;LOOK FOR SPACE
CALL GET_CHR ;GET LAST CHARACTER(S)
JC BAD ;IS GOOD
CMP AL,MAX_SEC ;WITHIN RANGE?
JG BAD ;NO
MOV BYTE PTR [SAV_SEC],AL ;SAVE GOOD BINARY
JMP SHORT CHKRES ;NOW, CHECK RESULTS
;
BAD: MOV DX,OFFSET PRP4 ;POINT TO USAGE
CALL PROMPT ;PRINT TO SCREEN
STC ;SHOW ERROR
RET
;
CHKRES: CALL CHK_TIM ;SEE IF WE ENTERED TIME PROPERLY
JNC TIMCHK ;IT WAS OK
MOV DX,OFFSET PRP5 ;POINT TO 'IMPROPER TIME'
CALL PROMPT ;PRINT
STC ;SHOW ERROR
RET
;
TIMCHK: PUSH SI ;CHECK RESULTS
MOV SI,OFFSET SAV_HRS ;WHERE BINARY IS
MOV DI,OFFSET HH ;WHERE TO PUT ASCII
CALL ASCIIM ;DO IT
MOV SI,OFFSET SAV_MIN ;WHERE BINARY IS
MOV DI,OFFSET MM ;WHERE TO PUT ASCII
CALL ASCIIM ;DO IT
MOV SI,OFFSET SAV_SEC ;WHERE BINARY IS
MOV DI,OFFSET SX ;WHERE TO PUT ASCII
CALL ASCIIM ;DO IT
;
MOV DX,OFFSET PRP0 ;POINT TO 'PROCESS'
CALL PROMPT ;PRINT TO SCREEN
;
MOV DI,CMD_BUF ;POINT TO COMMAND LINE
MOV AL,CL ;BYTE COUNT REMAINING
ADD AL,3 ;BYTES FOR ' \C '
STOSB
PUSH CX ;SAVE PRESENT COUNT
MOV CX,4 ;BYTES TO MOVE (TO WHERE TIME WAS)
MOV SI,OFFSET INFORM ;STRING TO MOVE
REP MOVSB ;MOVE INTO BUFFER
POP CX ;RESTORE COUNT
SUB CX,2 ;NO LEADING SPACE OR CARRIAGE RETURN
POP SI ;GET SAVED STRING POINTER
INC SI ;GET BY SPACE
JCXZ ABRT ;NOTHING TO LOAD
DISPL: LODSB ;GET BYTE
STOSB ;SAVE IN START OF BUFFER
CALL PCHR ;OUTPUT TO SCREEN
LOOP DISPL ;UNTIL DONE
MOV AL,CR ;BUFFER TERMINATION
STOSB
;
MOV DX,OFFSET PRP1 ;POINT TO 'IF NOT CORRECT..'
CALL PROMPT ;PRINT TO SCREEN
;
MOV CX,1000H ;TIMER
WAIT0: MOV AH,06H ;DIRECT CONSOLE INPUT
MOV DL,0FFH ;WE WANT A CHARACTER
INT MS_DOS ;FROM DOS
TEST AL,AL ;ANY CHARACTER?
JNZ ABRT ;YES, ABORT
TEST CL,CL ;NOPE, LOOK FOR CX = XX00
JNZ NO_DIS ;DON'T DISPLAY
MOV AL,CH ;GET HIGH BYTE
TEST AL,11111000B ;WITHIN RANGE YET?
JNZ NO_DIS ;NOPE, DON'T DISPLAY
AND AL,00000111B ;YES, MASK HIGH BITS
ADD AL,'0' ;CONVERT TO ASCII
CALL PCHR ;PRINT TO SCREEN
MOV AL,' ' ;GET A SPACE
CALL PCHR ;PRINT IT TOO
NO_DIS: LOOP WAIT0
;
MOV DX,OFFSET PRP3 ;POINT TO 'LOADED'
CALL PROMPT ;PRINT TO SCREEN
XOR AX,AX ;NO CARRY
RET
;
ABRT: MOV DX,OFFSET PRP2 ;POINT TO 'ABORTED'
CALL PROMPT ;PRINT TO SCREEN
STC
RET
PARSE ENDP
;
CHK_TIM PROC NEAR
MOV AL,BYTE PTR [SAV_HRS] ;GET COMMAND INPUT HOURS
CMP AL,BYTE PTR [HRS] ;GET PRESENT HOURS
JZ CHKMIN ;HOURS ARE THE SAME
JMP SHORT TIMBAD ;CARRY WILL SHOW ERROR
CHKMIN: MOV AL,BYTE PTR [SAV_MIN] ;GET COMMAND INPUT MINUTES
CMP AL,BYTE PTR [MIN] ;GET PRESENT MINUTES
JZ CHKSEC ;IF THE SAME
JMP SHORT TIMBAD ;CARRY SET IF BAD
CHKSEC: MOV AL,BYTE PTR [SAV_SEC] ;GET COMMAND INPUT SECONDS
CMP AL,BYTE PTR [SEC] ;GET PRESENT SECONDS
TIMBAD: RET
CHK_TIM ENDP
;
PCHR PROC NEAR ;PRINT CHARACTER IN AL, USES AX,DX
MOV DL,AL ;INTO DL
MOV AH,2 ;CONTROL BYTE
INT MS_DOS ;TO DOS
RET
PCHR ENDP
;
TELL PROC NEAR
MOV DX,OFFSET BEEP ;PRINT A BEEP
PROMPT PROC NEAR ;PRINT STRING ADDRESSED BY DX
MOV AH,9 ;FUNCTION
INT MS_DOS ;SYSTEM
RET
PROMPT ENDP
TELL ENDP
;
GET_CHR PROC NEAR ;GET CHARACTER [DI] POINTER
PUSH CX ;SAVE FOR NOW
REPNZ SCASB ;GET BY DELIMITER
POP BX ;SAVED AS FIRST COUNT (CX)
JCXZ BADENTRY ;WERE NO DEMITERS
SUB BX,CX ;BX= BYTES FROM SPACE TO ':'
CMP BX,2 ;WAS IT TWO BYTES?
PUSHF ;SAVE ANSWER TO THAT QUESTION
DEC DI ;BACK TO 'FOUND' CHARACTER
MOV SI,DI ;INTO SOURCE INDEX
SUB SI,BX ;BACK UP TO FIRST BYTE
LODSB ;GET BYTE
SUB AL,'0' ;ASCII BIAS
POPF ;ARE WE THROUGH?
JNZ ALLDUN
MOV BL,10 ;MULTIPLIER
MUL BL ;TIMES TEN
MOV AH,AL ;SAVE FOR NOW
LODSB ;GET NEXT BYTE IN STRING
SUB AL,'0' ;ASCII BIAS
ADD AL,AH ;ADD TOGETHER
ALLDUN: MOV DI,SI ;NEXT ADDRESS FOR COMPARE
INC DI
INC DI ;GET PAST THE COLON
OR AL,AL ;CLEAR CARRY
RET ;AL= BINARY FROM STRING
BADENTRY:
STC ;SHOW BAD
RET
GET_CHR ENDP
;
CASE PROC NEAR
PUSH SI ;SAVE INDEX
PUSH CX ;AND COUNT
MOV DI,SI ;DEST SAME AS SOURCE
CASE0: LODSB ;GET BYTE
CMP AL,'z' ;CHECK UPPER LIMIT
JG NO_CVT ;NOT A LOWER CASE LETTER
CMP AL,'a' ;CHECK LOWER LIMIT
JL NO_CVT ;NOT A LOWER CASE LETTER
AND AL,95 ;MASK LOWER CASE BITS
NO_CVT: STOSB ;SAVE IN STRING
LOOP CASE0
POP CX ;RESTORE COUNT
POP SI ;AND INDEX
RET
CASE ENDP
;
RUN_PG PROC NEAR ;LOAD AND EXECUTE PROGRAM
MOV WORD PTR [SSP_SAV],SP ;SAVE STACK POINTER
MOV AX,4B00H ;RUN PROGRAM EXE CALL
MOV BX,OFFSET BLOCK ;POINT TO PARAMETER BLOCK
MOV DX,OFFSET COMMAND ;POINT TO FILENAME
INT MS_DOS ;DO IT
MOV AX,CS ;GET GODE SEGMENT
MOV DS,AX ;SEGMENT FIXUPS
MOV ES,AX
MOV SS,AX ;FIX UP STACK SEGMENT
MOV SP,WORD PTR [SSP_SAV] ;RESTORE LOCAL STACK
RET
RUN_PG ENDP
;
KEEP3K PROC NEAR
MOV BX,OFFSET TOP ;PARAGRAPHS TO KEEP
MOV CL,4 ;BITS TO SHIFT
SHR BX,CL
INC BX ;ROUND UP
JMP SHORT FRE_MEM ;IMPLIED RETURN
KEEP3K ENDP
;
KEEP0K PROC NEAR
XOR BX,BX ;NO PARAGRAPHS
FRE_MEM PROC NEAR ;FREE UP MEMORY (PARAS IN BX)
MOV AH,4AH ;FUNCTION
PUSH ES ;SAVE, GET'S DESTROYED
INT MS_DOS ;DO IT
POP ES ;RESTORE EXTRA
RET
FRE_MEM ENDP
KEEP0K ENDP ;FALL THROUGH
;
SAV_SCR PROC NEAR ;SAVE ALL SCREEN PAGES BY BRUTE FORCE!
CALL GET_CUR ;SAVE CURSOR POSITION
CALL CREATE ;CREATE A SCREEN DATA FILE
CALL WRITE ;WRITE SCREEN DATA TO FILE
PUSHF ;SAVE POSSIBLE ERROR ON THE WRITE
CALL CLOSE ;CLOSE THE FILE
CALL CLR_SCR ;CLEAR THE SCREEN
POPF ;GET ERROR CODE FROM WRITE
JZ SAV_OK ;WAS ENOUGH SPACE
MOV DX,OFFSET ERRW ;POINT TO ERROR MESSAGE
CALL PROMPT ;PRINT TO SCREEN
SAV_OK: RET ;THAT'LL DO IT
SAV_SCR ENDP
;
GET_CUR PROC NEAR ;GET CURSOR POSITION
MOV AH,15 ;GET CURRENT STATE
INT VID_ROM
XOR BL,BL ;PAGE RETURNS IN BH
MOV BYTE PTR [CUR_PGE],BH ;SAVE CURRENT PAGE
MOV AH,3 ;FUNCTION
INT VID_ROM ;DO IT
MOV WORD PTR [CUR_SAV],DX ;SAVE CURSOR POSITION
MOV WORD PTR [CUR_TYP],CX ;SAVE CURSOR TYPE
RET
GET_CUR ENDP
;
RES_SCR PROC NEAR ;RESTORE SCREEN
CALL SET_CUR ;RESTORE OLD CURSOR POSITION
CALL OPEN ;OPEN THE SCREEN DATA FILE
CALL READ ;READ INTO SCREEN MEMORY
CALL CLOSE ;CLOSE THE FILE
CALL DELETE ;AND BLOW IT AWAY
RET
RES_SCR ENDP
;
SET_CUR PROC NEAR ;SET CURSOR TO SAVED POSITION
MOV AL,BYTE PTR [CUR_PGE] ;GET 'OLD' CURRENT PAGE
MOV AH,5 ;SELECT PAGE FUNCTION
INT VID_ROM ;DO IT
MOV AH,2 ;FUNCTION
MOV BH,BYTE PTR [CUR_PGE] ;PAGE
MOV DX,WORD PTR [CUR_SAV] ;GET OLD POSITION
INT VID_ROM ;DO IT
MOV AH,1 ;SET CURSOR TYPE
MOV CX,WORD PTR [CUR_TYP] ;GET CURSOR TYPE
INT VID_ROM
RET
SET_CUR ENDP
;
CLR_SCR PROC NEAR ;CLEAR THE SCREEN
MOV AX,0600H ;FUNCTION
XOR CX,CX ;TOP LEFT HAND CORNER
MOV DX,244FH ;BOTTOM RIGHT
MOV BH,7 ;NORMAL ATTRIBUTE
INT VID_ROM ;DO IT
XOR DX,DX ;TOP LEFT CORNER
MOV AH,2 ;SET CURSOR FUNCTION
MOV BH,0 ;PAGE ZERO
INT VID_ROM ;SET THE CURSOR
MOV AH,1 ;SET CURSOR TYPE
MOV CX,0608H ;START LINE 6, END LINE
INT VID_ROM
RET
CLR_SCR ENDP
;
SAV_DTA PROC NEAR ;SAVE USERS DTA
PUSH ES ;SAVE, SEGMENT IN RETURN
MOV AH,2FH ;GET PRESENT DTA
INT MS_DOS ;CALL DOS
MOV WORD PTR [DTA_SEG],ES ;SAVE PRESENT DTA SEGMENT
MOV WORD PTR [DTA_OFF],BX ;SAVE PRESENT DTA OFFSET
POP ES ;RESTORE SEGMENT
RET
SAV_DTA ENDP
;
SET_DTA PROC NEAR ;SET NEW DTA TO 'DEFAULT'
MOV AH,1AH ;FUNCTION
MOV DX,CMD_BUF ;DS:DX = 80H
INT MS_DOS ;DO IT
RET
SET_DTA ENDP
;
RES_DTA PROC NEAR ;RESTORE USER'S DTA
MOV AH,1AH ;FUNCTION
MOV DX,WORD PTR [DTA_OFF] ;GET OLD OFFSET
PUSH DS ;SAVE PRESENT DATA SEG
MOV DS,WORD PTR [DTA_SEG] ;NEW (OLD USER'S) DATA SEG
INT MS_DOS ;RESET TO OLD
POP DS ;RESTORE DATA SEG
RET
RES_DTA ENDP
;
RES_HRD PROC NEAR ;RESET HARDWARE CONTROLLER
MOV CX,5 ;FIVE POSSIBLE INTERRUPTS
MOV AL,20H ;NON-SPECIFIC END OF INTERRUPT
HRD: OUT INT_BASE,AL
LOOP HRD
RET
RES_HRD ENDP
;
SAV_DIR PROC NEAR
MOV AH,19H ;CURRENT DISK FUNCTION
INT MS_DOS
MOV BYTE PTR [DISK],AL ;SAVE
;
MOV AH,47H ;GET DIRECTORY FUNCTION
MOV SI,OFFSET DIRECT
MOV DL,0 ;CURRENT DISK
INT MS_DOS
RET
SAV_DIR ENDP
;
RES_DIR PROC NEAR
MOV AH,0EH ;SELECT DISK FUNCTION
MOV DL,BYTE PTR [DISK] ;GET SAVED DRIVE
INT MS_DOS ;DO IT
MOV AH,3BH ;CHANGE DIRECTORY FUNCTION
MOV DX,OFFSET DIRZ
INT MS_DOS
RET
RES_DIR ENDP
;
;
; The following routines are used to save the screen data on a disk.
;
COPY PROC NEAR ;COPY FILE NAME, DOS KILLS IT!!!
MOV SI,OFFSET FILE1 ;COPY FROM HERE
MOV DI,OFFSET FILE2 ;PUT IT THERE
MOV CX,FILEN ;BYTES TO COPY
REP MOVSB ;DO IT
RET
COPY ENDP
;
CREATE PROC NEAR
CALL COPY
MOV AH,3CH ;MS DOS FUNCTION
MOV DX,OFFSET FILE2 ;POINTER TO FILE NAME
XOR CX,CX ;NORMAL ATTRIBUTES
INT MS_DOS ;DO IT
MOV WORD PTR [HANDLE],AX ;SAVE HANDLE
RET
CREATE ENDP
;
OPEN PROC NEAR
CALL COPY ;GET NEW COPY OF FILE NAME
MOV AX,3D00H ;OPEN FUNCTION FOR READING
MOV DX,OFFSET FILE2 ;POINT TO FILE NAME
INT MS_DOS
MOV WORD PTR [HANDLE],AX ;SAVE ACCESS WORD
RET
OPEN ENDP
;
WRITE PROC NEAR
MOV AH,40H ;WRITE TO FILE FUNCTION
MOV BX,WORD PTR [HANDLE] ;GET OPEN FILE HANDLE
MOV CX,K16 ;16 K TO WRITE
PUSH DS ;SAVE DATA SEG
MOV DS,WORD PTR [SEGMNT] ;GET SCREEN SEGMENT
XOR DX,DX ;START AT THE BOTTOM
INT MS_DOS ;WRITE IT
POP DS ;RESTORE SEGMENT
CMP AX,K16 ;DID WE GET IT ALL?
RET
WRITE ENDP
;
READ PROC NEAR
MOV AH,3FH ;READ FILE FUNCTION
MOV BX,WORD PTR [HANDLE] ;FILE ACCESS WORD
MOV CX,K16 ;16 K TO READ INTO SCREEN
PUSH DS ;SAVE DATA SEGMENT
MOV DS,WORD PTR [SEGMNT] ;GET SCREEN SEGMENT
XOR DX,DX ;START AT THE BOTTOM
INT MS_DOS ;READ INTO SCREEN MEMORY
POP DS ;RESTORE
RET
READ ENDP
;
CLOSE PROC NEAR ;CLOSE THE SCREEN DATA FILE
MOV AH,3EH ;FUNCTION
MOV BX,WORD PTR [HANDLE] ;FILE ACCESS WORD
INT MS_DOS ;DO IT
RET
CLOSE ENDP
;
DELETE PROC NEAR ;DELETE SCREEN DATA FILE
CALL COPY ;GET FRESH COPY OF FILE NAME
MOV AH,41H ;DELETE FUNCTION
MOV DX,OFFSET FILE2 ;POINT TO FILE NAME
INT MS_DOS ;BLOW IT AWAY
RET
DELETE ENDP
;
; The following routines log the operation to disk
;
LOG PROC NEAR
CALL OPEN_LOG
CALL FIND_END
CALL GET_TIME
CALL GET_DATE
CALL GET_PROC
CALL WRITE_LOG
CALL CLOSE_LOG
RET
LOG ENDP
;
GET_TIME PROC NEAR
MOV AH,2CH ;GET TIME FUNCTION
INT MS_DOS
MOV DI,OFFSET TIME
MOV AL,CH ;HOURS TO AL
CALL ASCII ;CONV TO ASCII
INC DI ;GET BY ':'
MOV AL,CL ;MINUTES TO AL
CALL ASCII ;CONV TO ASCII
INC DI ;GET BY ':'
MOV AL,DH ;SECS TO AL
CALL ASCII ;CONVERT TO ASCII
RET
GET_TIME ENDP
;
GET_DATE PROC NEAR
MOV AH,2AH
INT MS_DOS
PUSH CX ;SAVE YEAR
MOV AL,DL ;GET DAY
MOV DI,OFFSET DATE
CALL ASCII
MOV DI,OFFSET DATE[3]
MOV AL,DH ;GET MONTHS
DEC AL ;JAN IS NOW ZERO OFFSET
CBW ;A WORD
MOV CL,3 ;MULTIPLIER (THREE CHRS PER MONTH)
MUL CL ;CALC OFFSET
MOV SI,OFFSET MONTH ;POINT TO TABLE
ADD SI,AX ;NEW OFFSET
MOV CX,3 ;CHRS TO MOVE
REP MOVSB ;DO IT
POP CX
SUB CX,1900 ;NORMALIZE
MOV AL,CL
MOV DI,OFFSET DATE[7]
CALL ASCII
RET
GET_DATE ENDP
;
GET_PROC PROC NEAR
MOV WORD PTR [BYTES],0 ;BYTE COUNT
MOV SI,CMD_BUF ;POINT TO COMMAND LINE
MOV DI,OFFSET LINEBUF ;WHERE TO PUT THE STRING
LODSB ;GET CHARACTERS TYPED
SUB AL,3 ;SUBTRACT FOR ' /C'
CBW
MOV CX,AX ;BYTE COUNT
JCXZ GETOUT ;NOTHING TYPED
ADD AX,LEN ;PLUS THE TIME/DATE STAMP
MOV WORD PTR [BYTES],AX ;SAVE FOR FILE WRITE
ADD SI,3 ;GET BY THE ' /C'
REP MOVSB ;MOVE THE STRING
GETOUT: RET
GET_PROC ENDP
;
OPEN_LOG PROC NEAR
MOV DX,OFFSET LOGF ;POINT TO LOG FILE NAME
MOV AX,3D02H ;OPEN FOR R/W
XOR CX,CX ;NORMAL FILE
INT MS_DOS
JNC OPNGD ;GOOD OPEN
MOV AX,3C00H ;CREATE THE FILE, NONE EXISTS
MOV DX,OFFSET LOGF ;POINT TO FILE NAME
XOR CX,CX ;NORMAL FILE
INT MS_DOS
OPNGD: MOV WORD PTR [LOGCHAN],AX ;SAVE CHANNEL ACCESS WORD
RET
OPEN_LOG ENDP
;
FIND_END PROC NEAR
MOV AX,4202H ;MOVE TO END PLUS OFFSET
XOR CX,CX
MOV DX,CX ;NO OFFSET
MOV BX,WORD PTR [LOGCHAN] ;GET HANDLE
INT MS_DOS ;DO IT
RET
FIND_END ENDP
;
WRITE_LOG PROC NEAR
MOV AX,4000H ;WRITE TO FILE
MOV DX,OFFSET LINE ;POINT TO THE STRING TO BE WRITTEN
MOV BX,WORD PTR [LOGCHAN] ;HANDLE
MOV CX,WORD PTR [BYTES] ;NOW MUCH TO WRITE
JCXZ NOWRT
INT MS_DOS
NOWRT: RET
WRITE_LOG ENDP
;
CLOSE_LOG PROC NEAR
MOV AX,3E00H ;CLOSE FILE
MOV BX,WORD PTR [LOGCHAN] ;FILE ACCESS WORD
INT MS_DOS
RET
CLOSE_LOG ENDP
;
ASCIIM PROC NEAR ;BINARY(M) TO ASCII
LODSB
ASCII PROC NEAR ;CONV BINARY IN AL TO ASCII [DI]
MOV AH,'0'-1 ;ASCII BIAS
SUBT: INC AH ;TENS COUNTER
SUB AL,10 ;SUBTRACT TENS
JNC SUBT ;CONTINUE
ADD AL,(10 + '0') ;ONE TOO MANY ADD BACK PLUS ASCII BIAS
XCHG AH,AL ;SWAP FOR STRING STORE
STOSW ;DO IT
RET
ASCII ENDP
ASCIIM ENDP
;
TOP EQU $
IF1
%OUT -------
ENDIF
PSEG ENDS
END MAIN