MS-DOS/v2.0/source/TIME.ASM
2018-09-21 17:53:34 -07:00

231 lines
6.9 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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