231 lines
6.9 KiB
NASM
231 lines
6.9 KiB
NASM
;
|
||
; 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
|
||
|