Category : Utilities for DOS and Windows Machines
Archive   : ATNUDGE2.ZIP
Filename : ATCLOCK.ASM

 
Output of file : ATCLOCK.ASM contained in archive : ATNUDGE2.ZIP
page 64,130
Title E ATCLOCK - Daily housekeeping.F
;box
;ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
;³ Created 2 Jan. '88 ³
;³ Date of last revision: 07-Sep-1988 ³
;ÆÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵
;³ ATCLOCK.ASM ³
;³ ³
;³ Single segment '.COM' type program. ³
;³ Description of function: Checks for 1st time run today ³
;³ from 'TODAY.AT' file. Nudges clock if so. ³
;³ Keeps standard/daylight time, changes 1 hour if needed. ³
;³ Set nudge value with '/Nxxx', daylight-std with '/D','/S'. ³
;³ ³
;ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;
;ebx
; 3 April '88 - Daylight savings time!
; 5 Sept. '88 - Major revision. Midnight rollover,
; multiple days, daylight/standard comands.
; Macros used for messages to stdout. Structure for date file.
; Uses .286 mode. Program is not re-entrant.
; Link with: ASMUTILS.LIB
;
.286
INCLUDE ASMUTILS.ASI
.SALL
CSEG SEGMENT PARA PUBLIC 'CODE' ;Segments at beginning,
CSEG ENDS
MSGSEG SEGMENT BYTE PUBLIC 'CODE' ;Message data at end.
MSGSEG ENDS
CGroup GROUP CSEG,MSGSEG ;All really the same segment.
; ; Flag bits for /Commands.
NewNudge EQU 1
DSCmdRcvd EQU 2
Daylite EQU 4
OneNudge EQU 8
;
DateInfo STRUC
PDATE DB ' '
DOW DB ?,?,?,? ; Today's date with month/day names.
DOM DB ?,?,? ; Like " Sun 08 Jan 1989 "
MONTH DB ?,?,?,?
CENTURY DB ?,?
YEAR DB ?,?,' '
StOrDl DB 'S' ; S-standard time, D-daylight.
BinYear DW ? ; Year in binary.
JulDate DW ? ; Julian date in binary.
PDATNUMS DB 6 DUP (?) ; Date in numbers. Like: "890108"
AscNudge DB 5 DUP (?) ; Nudge value. Like "-0182"
DateInfo ENDS
PAGE
SEGZERO SEGMENT AT 0
ORG 46CH ;Time info in BIOS' data area.
TimerLow DW ?
TimerHigh DW ?
SEGZERO ENDS
;
CSEG SEGMENT
ASSUME CS:CGroup,DS:CGroup
EXTRN Asc2Bin:NEAR, SkipSpac:NEAR, AX4Digs:NEAR, DispDOSMsg:NEAR,\
NextLine:NEAR, SimplMsg:NEAR, ProgName:NEAR
ORG 100H
START: JMP PROG
SCommands DB 0 ;Flags for '/' commands.
NudgeVal DW 0 ;# ticks to nudge clock.
DOSDate DateInfo <>
; ;Structure expansion edited out of listing.
TFDate DateInfo <>
MsgSize EQU OFFSET DOSDate.StOrDl - OFFSET DOSDate
TFSiz EQU TYPE DOSDate ; Size of our data file.
DaysPassed DW 0 ;#days to adjust for, calculated if needed.
CMOSCent DB 19H
CMOSYear DB ?
CMOSMon DB ?
CMOSDay DB ?
DaysPerMon DB 31
DaysInFeb DB 28,31,30,31,30,31,31,30,31,30
DAYS DB 'Sun Mon Tue Wed Thu Fri Sat '
MOS DB 'JanFebMarAprMayJunJulAugSepOctNovDec'
TimeDisp DB ' '
TimeData DB ?,?,':',?,?,':',?,?
TFName DB 60 DUP (?)
TodayAT DB 'TODAY.AT',0
CmdLtrs DB '1DNS'
CmdProcs DW OneCmd,DSCmds,NCmd,DSCmds
ULine DB 2,0 ;Buffer to get a 'y' or 'n'.
UResp DB 0,0
PAGE
; ; --- Begin main program ---
PROG PROC NEAR
CLD
; ; Check DOS Version
MOV AH,30H ; Check for DOS Version 3.0+.
INT 21H
CMP AL,3
JAE @F ; If so, continue.
DMessage <"ATCLOCK: Requires DOS 3 or above!"> \
AddLine+ErrorMsg+NoRet ;Macro for display error and abort.
; ; This error message won't even work under DOS 1.0!
;
; ; Check command line for /N /D /S or /1 commands.
@@: MOV SI,80H ;Read data from PSP 'till we get
LODSB ; '/' or end of line.
CMP AL,02 ;Must be 2 chars entered.
JB GetPath
CALL SkipSpac ;Skip spaces after '/'.
ReadCmds: LODSB
CMP AL,0DH
JE GetPath
CMP AL,'/'
JNE ReadCmds
LODSB
CMP AL,0DH
JE GetPath
AND AL,0DFH ;Force upper case.
MOV DI,OFFSET CmdLtrs ;Check for a match to one
MOV CX,CmdProcs - CmdLtrs ; of our commands.
REPNE SCASB
JNE ReadCmds ;Loop if no match.
SUB DI,OFFSET CmdLtrs + 1 ;DI = Command index.
SHL DI,1 ;DI = offset in table.
CALL CmdProcs[DI] ;Execute the command.
JMP ReadCmds
;
; ; Get the path to our directory. Generate date file's name.
GetPath: PUSH DS ;Save our segment.
CALL ProgName ;Get path name to this prog in DS:SI.
MOV DI,OFFSET TFName ;Move path into name field for
REP MOVSB ; our data file.
POP DS ;Get our segment back and move in
MOV SI,OFFSET TodayAT ; filename after path.
MOV CX,9
REP MOVSB
;
; ; Get the date and compare with the date file.
CALL DateData ; Convert DOS date to our formats.
CALL GetDateFile ; Try to read in the date file.
JC ReWrite ;Skip tests if no file.
;
; ; File read OK. Check dates.
MOV SI,OFFSET DOSDate.BinYear ;[SI]-DOS' numeric date.
MOV DI,OFFSET TFDate.BinYear ;[DI]-File's " "
MOV CX,05 ;2 words + 6 digits.
REPE CMPSW ;Compare.
JE CheckDS ;Branch if same day.
PAGE
; ; New day. Calculate the number that have passed.
TEST SCommands,OneNudge
JZ @F ;Set single day if /1 command.
MOV DaysPassed,1
JMP SHORT CheckDS
@@: CALL GetPassed
CMP DaysPassed,0 ;File error if no days passed.
JE ReWrite ;Ignore old file, rewrite.
;
; ; File data is good. Check Std/Daylight params.
CheckDS: MOV AL,TFDate.StOrDl ;Get file's param.
CMP AL,DOSDate.StOrDl ;Old = New ?
JE @F ;Branch if so.
TEST SCommands,DSCmdRcvd ;Did we get a command?
JNZ DSChange ;Branch if we did.
MOV DOSDate.StOrDl,AL ;No command, set new=old.
@@: CMP DaysPassed,0 ;Nudge if new day.
JNE NewDay
TEST SCommands,NewNudge ;Not new day. Rewrite file if
JZ SetCMOS ;a new nudge value was entered.
ReWrite: CALL WrDateFile
JMP SHORT SetCMOS ;Just set the clock if not.
;
; ; We have a command to exchange daylight <> standard.
DSChange: CALL TimeChange ;Ask for confirm, change if OK.
CMP DaysPassed,0 ; If no nudge required, write
JE WrtToday ; the date file and quit.
;
; ; New day - nudge the clock.
NewDay: TEST SCommands,NewNudge ;Did we set new nudge value?
JNZ @F ;Branch if yes.
MOV SI,OFFSET TFDate.AscNudge
MOV CX,04 ;Convert 4 digits to binary.
CALL Asc2Bin
MOV NudgeVal,AX ;Save as current nudge value.
@@: MOV AX,NudgeVal ;Get amount to adjust.
TEST AX,AX ;Skip this if it's zero.
JZ WrtToday
IMUL DaysPassed ;Ticks per day * Number of days.
CALL AdjustDOS ; Adjust the DOS clock first.
;
; ; Clock twiddling done if needed. Update file, set clock.
WrtToday: CALL WrDateFile ; Write new date file.
CALL DateData ; Recalculate the date params from DOS.
SetCMOS: CALL SetATClock ; Set the CMOS clock.
;
; ; Display current date, time.
MOV DX,OFFSET DOSDate ;Write date to screen.
MOV CX,MsgSize
MOV AH,AddLine
CALL SimplMsg
MOV DX,OFFSET TimeDisp ;Write time to screen.
MOV CX,9 ;9 characters, + CrLf.
MOV AH,AddLine
CALL SimplMsg
RET
PROG ENDP
; ; *** End main program ***
PAGE
; ; Command response functions.
; ; /1 command - Nudge clock by one day only.
OneCmd PROC NEAR ;Just set the flag.
OR SCommands,OneNudge
RET
OneCmd ENDP
;
; ; /N command - set new nudge value.
NCmd PROC NEAR
CALL SkipSpac ;Skip spaces after 'N'.
MOV CX,04 ;Get up to four digits.
CALL Asc2Bin
CMP CX,04 ;Did we get any digits?
JE @F ;Branch if no - leave it zero.
MOV NudgeVal,AX ;Set new value and flag.
OR SCommands,NewNudge ;(could be 0).
@@: RET
NCmd ENDP
;
; ; /S or /D commands - Standard or Daylight.
DSCmds PROC NEAR
OR SCommands,DSCmdRcvd ;Set command flag.
MOV DOSDate.StOrDl,AL ;Save the letter.
RET
DSCmds ENDP
;
; ; Subroutines for clock prog.
GetDateFile PROC NEAR ;Try to open the date file.
MOV DX,OFFSET TFName ;We will return carry set if fail.
MOV AX,3D02H ;Read/write access.
INT 21H
JC NoDF ;Return error if no file.
; ; The file is open. Try to read it.
MOV BX,AX ;Handle to BX.
MOV CX,TFSiz ;# bytes to CX.
MOV DX,OFFSET TFDate
MOV AH,3FH ;'Read from file or device'
INT 21H
JC ReadErr ;Must have no DOS error and #bytes
CMP AX,CX ; read = # requested or file NG.
JE ReadOK
ReadErr: MOV AH,3EH ;Error on read. Close file, forget.
INT 21H ;Ignore close errors.
STC ;Return fail.
JMP SHORT NoDF
ReadOK: MOV AH,3EH ;Close file so we can re-write it.
INT 21H ;Clears carry.
NoDF: RET
GetDateFile ENDP
PAGE
; ; Get date from DOS. Setup our data area with:
; ; 1. Full date in Ascii for display & date file.
; ; 2. Date in numbers for date file / compare.
; ; 3. Julian day, year in binary for days passed calculate.
; ; 4. Binary format needed by CMOS clocks.
DateData PROC NEAR
MOV DI,OFFSET DOSDate.PDATE
MOV AX,2A20H ;Put a space at beginning.
STOSB ;Revise date string from start.
INT 21H ;DOS Get date call.
MOV DOSDate.BinYear,CX ;Save year. AL has day-of-week.
; ;Day of week.
MOV SI,OFFSET DAYS
XOR AH,AH ;Multiply days x4 for offset
ADD SI,AX ; into table.
CALL SetDM ;Convert & store.
; ;Day of month in Ascii.
MOV AL,DL ;Day of month in binary.
CALL ConvDig ;Convert & store.
MOV CMOSDay,AL ;Save for setting clock.
MOV BYTE PTR [DI],' ' ;Add a space.
MOV AX,WORD PTR DosDate.DOM ;Put same value in numeric
MOV WORD PTR DOSDate.PDATNUMS + 4,AX ;date.
; ;Month.
MOV AL,DH ;Get month number, 1-12 (not 0-11)
MOV DI,OFFSET DOSDate.PDATNUMS + 2 ; for variety.
CALL ConvDig ;Put in numeric date field.
MOV CMOSMon,AL ;Save for setting clock.
MOV AL,DH ;Adjust and put month name in.
DEC AL
MOV DI,OFFSET DOSDate.MONTH
MOV SI,OFFSET MOS ;Months calculated like days.
CALL SetDM
; ;Julian date in binary.
MOV AX,DX ;Binary month/day to AH/AL.
MOV DX,DOSDate.BinYear ;Binary year to DX.
CALL JulianDate ;Get Julian date in AX.
MOV DOSDate.JulDate,AX ;Save for file.
; ;Year.
MOV AX,'91' ;Put in '19'.
SUB DX,1900 ;Get (Year-1900).
CMP DX,100
JB Twentieth
MOV CMOSCent,20H
MOV AX,'02' ;Change after 2000.
SUB DX,100
Twentieth: STOSW
MOV AL,DL ;Put year in AL.
CALL ConvDig
MOV CMOSYear,AL ;Save for setting clock.
MOV BYTE PTR [DI],' '
MOV AX,[DI-2] ;Put year in numeric date.
MOV WORD PTR DOSDate.PDATNUMS,AX
RET
DateData ENDP
PAGE
; ; Calculate number of days passed since last run.
GetPassed PROC NEAR
MOV AX,DOSDate.JulDate ;Today's Julian date, year.
MOV BX,DOSDate.BinYear
SUB BX,TFDate.BinYear ;Get # years gone by.
JZ @F ;Branch if none.
DEC BX ;Sanity check.
JNZ DFNoGood ;Branch if > 1 year.
ADD AX,365 ;Correct for a year. Check for
TEST BYTE PTR TFDate.BinYear,03 ; last year was a leap.
JNZ @F ;Branch if it wasn't.
INC AX ;One more day to correct.
@@: SUB AX,TFDate.JulDate
JC DFNoGood ;Branch if today < yesterday.
TEST AH,AH ;Check for difference > 255.
JZ @F ;Branch if not - file is OK.
DFNoGood: DMessage <"ATCLOCK: Date file invalid!"> \
AddLine+ErrorMsg+NoRet ; Return w/o updating DaysPassed.
@@: MOV DaysPassed,AX ;Save # days to adjust for.
RET
GetPassed ENDP
;
; ; Change daylight - standard after confirmation.
TimeChange PROC NEAR
@@: DMessage <"Do you want to set the clock ">
CMP DOSDate.StOrDl,'D' ;Ask for confirmation.
JE @F ;Branch if going to daylight.
DMessage <"back 1 hour for standard time? ">
JMP SHORT WaitConf
@@: DMessage <"ahead 1 hour for daylight time? ">
WaitConf: CALL GetYorN ;Wait for response.
JNE NoTC ;Branch if 'No'.
MOV DX,1 ;Set one hour's worth of ticks.
MOV AX,7
CMP DOSDate.StOrDl,'D' ;Are we going to daylight?
JE @F ;Branch if positive adjust.
NEG AX ;Add negative 1 hour.
NOT DX
@@: CALL AdjustDOS ;Enter correction to DOS clock only.
DMessage <"Time change set."> AddLine
NoTC: RET
TimeChange ENDP
;
; ; Adjust the DOS clock by DX:AX ticks (signed).
AdjustDOS PROC NEAR
XOR BX,BX ;Get access to data area.
MOV DS,BX
ASSUME DS:SEGZERO ;Inform MASM.
CLI ;Hold the clock off.
ADD AX,TimerLow ; Get the adjusted values in AX:DX.
ADC DX,TimerHigh
CMP DX,23 ;Check for over/underflow.
JA DayChange ;Branch if so.
JB @F ;Branch elsewhere if < 23Hrs.
CMP AX,7*24 ;Check for > 23:59.
JAE DayChange
@@: CALL TicsDays ;No overflow. Set clock, reload seg.
JMP SHORT AdjDone
;
DayChange: TEST DH,80H ;Date rolled.
JZ Manana ;Branch if forward.
ADD AX,7*24 ;It's yesterday.
ADC DX,24 ;Put 24 hrs. back into clock.
CALL TicsDays ;Set clock, int on, reload seg.
DEC AX ;Take the 1 day out of the calendar.
JNZ @F ;Branch if same year.
DEC DX ;Now NewYears' Eve.
MOV AX,365
TEST DX,03
JNZ @F
INC AX ;Now New Years' Eve of a leap year!
@@: JMP SHORT NewDate
;
Manana: SUB AX,7*24 ;Take the day back out of the clock.
SBB DX,24
CALL TicsDays ;Set clock, int on, reload seg.
ASSUME DS:CGroup ;Don't mislead Masm.
INC AX ;Put the day into the calendar.
MOV BX,365 ;Set BX to #days this year.
TEST DX,03
JNZ @F
INC BX ;It's a leap year.
@@: CMP AX,BX ;Check for year rolled.
JBE NewDate
INC DX
MOV AX,1 ;Happy New Year!
NewDate: CALL Jul2DOS ;Set the new date in DOS.
AdjDone: DMessage <"Clock adjusted."> AddLine
RET
AdjustDos ENDP
;
; ; Write new date file. Set nudge value from variable.
WrDateFile PROC NEAR
MOV AX,NudgeVal ;Convert nudge value to ascii in
MOV DI,OFFSET DOSDate.AscNudge ;date info.
CALL AX4Digs
MOV DX,OFFSET TFName ;Create or overwrite 'Today'.
XOR CX,CX ;Normal, visible file.
MOV AH,3CH
INT 21H
JC WritErr ;Bail out if error on create.
MOV BX,AX ;File handle to BX.
MOV CX,TFSiz ;# bytes to CX.
MOV DX,OFFSET DOSDate ;DX -> data to write.
MOV AH,40H ;'Write to file or device'.
INT 21H
JC WritErr ;Bail on error.
CMP AX,CX ;Also if disk full .
JE WriteOK
WritErr: DMessage <"ATCLOCK: DOS error writing data file!"> \
AddLine+ErrorMsg
WriteOK: MOV AH,3EH ;Close the file.
INT 21H ;Ignore errors. Can't do anything.
RET
WrDateFile ENDP
PAGE
; ;Set the CMOS clock from the DOS clock.
SetATClock PROC NEAR
MOV AH,2CH ;Let DOS convert the raw ticks to
INT 21H ; hr:min:sec. We don't care if a
CMP DL,45 ; tick went by. Round off DOS'
JB @F ; ".01" seconds.
INC DH
; ;Change DOS time data to clock data format.
@@: MOV DI,OFFSET TimeData ;Point to time display data.
MOV AL,CH ;Convert hours for display and
CALL ConvDig ; to BCD for CMOS clock call.
INC DI ;Skip the colon.
MOV CH,AL
MOV AL,CL ;Same for minutes.
CALL ConvDig
INC DI ;Skip the colon.
MOV CL,AL
MOV AL,DH ;Same for seconds.
CALL ConvDig
INC DI ;Skip the colon.
MOV DH,AL
XOR DL,DL ;DL=0 for standard time,
CMP DOSDate.StOrDl,'D'
JNE @F ; 1 for daylight.
INC DL
@@: MOV AH,03
INT 1AH ;Set the CMOS clock.
; ;Set the date from our date from DOS.
MOV CH,CMOSCent ;Good for 112 more years...
MOV CL,CMOSYear
MOV DH,CMOSMon
MOV DL,CMOSDay
MOV AH,05
INT 1AH ;Set the date.
RET
SetATClock ENDP
;
; ; Julian date: From month/day in AH/AL,
JulianDate PROC NEAR ; Binary year in DX. Result in AX.
PUSH DX
MOV CL,28 ;Default 28 days in Feb.
TEST DX,03 ;Non-zero means non leap year.
JNZ @F ;Good for years between 1900 & 2100.
INC CL
@@: MOV DaysInFeb,CL ;Set February.
MOV SI,OFFSET DaysPerMon
XOR CX,CX
MOV DX,CX
XCHG CL,AH ;Add days per month oneata time.
MOV DL,AL ;Accumulate in DX.
DEC CX ;Months 0-11.
JZ @F ;No correction for January.
NxtMonth: LODSB
ADD DX,AX
LOOP NxtMonth
@@: MOV AX,DX ;Result in right place.
POP DX
RET
JulianDate ENDP
;
; ; Jul2DOS: Convert Year:Julian in DX:AX to DOS format
; ; and set the DOS clock.
Jul2DOS PROC NEAR
MOV CX,DX ;Year same format.
MOV SI,OFFSET DaysPerMon
MOV BL,28 ;Set correct #days in Feb.
TEST DX,03
JNZ @F
INC BL
@@: MOV DaysInFeb,BL
XOR DX,DX
MOV BX,DX ;Clear scratch regs.
IncMos: INC DH ;Add to months & subtract days.
TEST AH,AH ;Skip check if still > 255.
JNZ @F
CMP AL,[SI] ;Conversion done if
JBE Found ; AX < #days in month DH.
@@: MOV BL,[SI]
SUB AX,BX ;Subtract the month, loop.
INC SI
JMP IncMos
Found: MOV DL,AL ;Set proper regs for DOS.
MOV AH,2BH ;Set DOS date.
INT 21H
RET
Jul2DOS ENDP
;
; ; Get yes or no response from user.
GetYorN PROC NEAR
MOV DX,OFFSET ULine
MOV AH,0AH ;Via redirectable call.
INT 21H
XOR AH,AH ;No options for message.
CALL NextLine ;cr,lf...
MOV AL,UResp ;Get the letter.
AND AL,0DFH ;Force upper case.
CMP AL,'Y' ;It's Y or it's not!
RET
GetYorN ENDP
;
TicsDays PROC NEAR ;Set Bios clock, load date.
ASSUME DS:SEGZERO
MOV TimerLow,AX
MOV TimerHigh,DX
STI ;Int back on, get our segment.
MOV AX,CS
MOV DS,AX
ASSUME DS:CGroup
MOV AX,DOSDate.JulDate ;DX:AX = Year:Julian date.
MOV DX,DOSDate.BinYear
RET
TicsDays ENDP
PAGE
; ; Update day or month data.
SetDM PROC NEAR
XOR AH,AH ;Mult. AL x3 for data address
ADD SI,AX ;in list. Move data to o/p area.
SHL AL,1
ADD SI,AX
MOV CX,03
REP MOVSB
MOV AL,' '
STOSB ;Add space after data.
RET
SetDM ENDP
;
; ; Convert binary # in AL to 2-digit Ascii for display
; ; and packed BCD for CMOS clock set call. Uses BX.
ConvDig PROC NEAR
AAM ;AL to unpacked BCD in AH,AL.
MOV BX,AX ;Save for further convert.
OR AX,3030H ;Change to Ascii.
XCHG AL,AH ;Change to Intel.
STOSW ;Save for display.
MOV AL,BL ;Get LS nibble.
SHL BH,4 ;OR in MS nibble.
OR AL,BH
RET
ConvDig ENDP
CSEG ENDS
END START


  3 Responses to “Category : Utilities for DOS and Windows Machines
Archive   : ATNUDGE2.ZIP
Filename : ATCLOCK.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/