MS-DOS/v2.0/source/TIME.ASM

231 lines
6.9 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
;
; Time and date functions for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE TIME - time and date functions
NAME TIME
i_need DAY,BYTE
i_need MONTH,BYTE
i_need YEAR,WORD
i_need WEEKDAY,BYTE
i_need TIMEBUF,6
i_need BCLOCK,DWORD
i_need DAYCNT,WORD
i_need YRTAB,8
i_need MONTAB,12
FOURYEARS = 3*365 + 366
SUBTTL DATE16, READTIME, DODATE -- GUTS OF TIME AND DATE
PAGE
;
; Date16 returns the current date in AX, current time in DX
; AX - YYYYYYYMMMMDDDDD years months days
; DX - HHHHHMMMMMMSSSSS hours minutes seconds/2
;
procedure DATE16,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
PUSH CX
PUSH ES
CALL READTIME
POP ES
SHL CL,1 ;Minutes to left part of byte
SHL CL,1
SHL CX,1 ;Push hours and minutes to left end
SHL CX,1
SHL CX,1
SHR DH,1 ;Count every two seconds
OR CL,DH ;Combine seconds with hours and minutes
MOV DX,CX
MOV AX,WORD PTR [MONTH] ;Fetch month and year
MOV CL,4
SHL AL,CL ;Push month to left to make room for day
SHL AX,1
POP CX
OR AL,[DAY]
RET
DATE16 ENDP
procedure READTIME,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
;Gets time in CX:DX. Figures new date if it has changed.
;Uses AX, CX, DX.
PUSH SI
PUSH BX
MOV BX,OFFSET DOSGROUP:TIMEBUF
MOV CX,6
XOR DX,DX
MOV AX,DX
invoke SETREAD
PUSH DS
LDS SI,[BCLOCK]
ASSUME DS:NOTHING
invoke DEVIOCALL2 ;Get correct date and time
POP DS
ASSUME DS:DOSGROUP
POP BX
POP SI
MOV AX,WORD PTR [TIMEBUF]
MOV CX,WORD PTR [TIMEBUF+2]
MOV DX,WORD PTR [TIMEBUF+4]
CMP AX,[DAYCNT] ;See if day count is the same
JZ RET22
CMP AX,FOURYEARS*30 ;Number of days in 120 years
JAE RET22 ;Ignore if too large
MOV [DAYCNT],AX
PUSH SI
PUSH CX
PUSH DX ;Save time
XOR DX,DX
MOV CX,FOURYEARS ;Number of days in 4 years
DIV CX ;Compute number of 4-year units
SHL AX,1
SHL AX,1
SHL AX,1 ;Multiply by 8 (no. of half-years)
MOV CX,AX ;<240 implies AH=0
MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year
CALL DSLIDE ;Find out which of four years we're in
SHR CX,1 ;Convert half-years to whole years
JNC SK ;Extra half-year?
ADD DX,200
SK:
CALL SETYEAR
MOV CL,1 ;At least at first month in year
MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month
CALL DSLIDE ;Find out which month we're in
MOV [MONTH],CL
INC DX ;Remainder is day of month (start with one)
MOV [DAY],DL
CALL WKDAY ;Set day of week
POP DX
POP CX
POP SI
RET22: RET
READTIME ENDP
procedure DSLIDE,NEAR
MOV AH,0
DSLIDE1:
LODSB ;Get count of days
CMP DX,AX ;See if it will fit
JB RET23 ;If not, done
SUB DX,AX
INC CX ;Count one more month/year
JMP SHORT DSLIDE1
DSLIDE ENDP
procedure SETYEAR,NEAR
;Set year with value in CX. Adjust length of February for this year.
MOV BYTE PTR [YEAR],CL
CHKYR:
TEST CL,3 ;Check for leap year
MOV AL,28
JNZ SAVFEB ;28 days if no leap year
INC AL ;Add leap day
SAVFEB:
MOV [MONTAB+1],AL ;Store for February
RET23: RET
SETYEAR ENDP
procedure DODATE,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
CALL CHKYR ;Set Feb. up for new year
MOV AL,DH
MOV BX,OFFSET DOSGROUP:MONTAB-1
XLAT ;Look up days in month
CMP AL,DL
MOV AL,-1 ;Restore error flag, just in case
JB RET25 ;Error if too many days
CALL SETYEAR
MOV WORD PTR [DAY],DX ;Set both day and month
SHR CX,1
SHR CX,1
MOV AX,FOURYEARS
MOV BX,DX
MUL CX
MOV CL,BYTE PTR [YEAR]
AND CL,3
MOV SI,OFFSET DOSGROUP:YRTAB
MOV DX,AX
SHL CX,1 ;Two entries per year, so double count
CALL DSUM ;Add up the days in each year
MOV CL,BH ;Month of year
MOV SI,OFFSET DOSGROUP:MONTAB
DEC CX ;Account for months starting with one
CALL DSUM ;Add up days in each month
MOV CL,BL ;Day of month
DEC CX ;Account for days starting with one
ADD DX,CX ;Add in to day total
XCHG AX,DX ;Get day count in AX
MOV [DAYCNT],AX
PUSH SI
PUSH BX
PUSH AX
MOV BX,OFFSET DOSGROUP:TIMEBUF
MOV CX,6
XOR DX,DX
MOV AX,DX
PUSH BX
invoke SETREAD
ASSUME ES:DOSGROUP
PUSH DS
LDS SI,[BCLOCK]
ASSUME DS:NOTHING
invoke DEVIOCALL2 ;Get correct date and time
POP DS
POP BX
ASSUME DS:DOSGROUP
invoke SETWRITE
POP WORD PTR [TIMEBUF]
PUSH DS
LDS SI,[BCLOCK]
ASSUME DS:NOTHING
invoke DEVIOCALL2 ;Set the date
POP DS
ASSUME DS:DOSGROUP
POP BX
POP SI
WKDAY:
MOV AX,[DAYCNT]
XOR DX,DX
MOV CX,7
INC AX
INC AX ;First day was Tuesday
DIV CX ;Compute day of week
MOV [WEEKDAY],DL
XOR AL,AL ;Flag OK
RET25: RET
DODATE ENDP
procedure DSUM,NEAR
MOV AH,0
JCXZ RET25
DSUM1:
LODSB
ADD DX,AX
LOOP DSUM1
RET
DSUM ENDP
do_ext
CODE ENDS
END