home *** CD-ROM | disk | FTP | other *** search
- PAGE 66,132
- ;****************************************************************************
- ;
- ; PROGRAM: CLOCK
- ;
- ; DESCRIPTION: PRINT DATE AND TIME ON SCREEN
- ;
- ; INPUT: NONE
- ;
- ; OUTPUT: CURRENT DATE AND TIME ON SCREEN
- ;
- ; TYPE OF FILE: .COM FILE
- ;
- ; COMMENTS: THIS PROGRAM WILL PICK UP THE CURRENT DATE AND TIME AND
- ; DISPLAY DAY, DATE AND TIME ON THE SCREEN. DATE IS FORMATTED OUT
- ; TO MONTH NAME, DAY AND YEAR, TIME IS HH:MM:SS. THIS PROGRAM WILL
- ; LOOP UNTIL CONTROL BREAK IS INTERCEPTED.
- ;
- ; TO INCREASE READABILITY OF THE DISPLAY, IT WILL SAVE THE CURRENT
- ; CURSOR TYPE, AND ERASE THE CURSOR. WHEN CONTROL-BREAK IS DETECTED,
- ; THE PROGRAM WILL INTERCEPT THE INTERRUPT AT ROUTINE TERMIN, RESTORE
- ; THE CURSOR AND TERMINATE.
- ;
- ; THIS PROGRAM ALSO CHECKS FOR DOS 2.0 OR ABOVE, AND IF IT IS NOT
- ; PRESENT, TERMINATE IMMEDIATELY
- ;
- ; THIS PROGRAM USES THE EQUATIONS FROM WES MEIER'S DFACT.BAS TO COMPUTE
- ; THE DAY OF THE WEEK. THEY ARE:
- ;
- ; F = 365 * YEAR + DAY + (31 * (MONTH - 1))
- ;
- ; IF MONTH < 3 THEN F = F + INT ((YEAR - 1) / 4) -
- ; INT ((INT ((YEAR / 100) + 1)) * 3 / 4)
- ;
- ; IF MONTH >= 3 THEN F = F + INT ((MONTH + 23) * 4 / 10) +
- ; INT (YEAR / 4) - INT ((INT (YEAR / 100) + 1) * 3 / 4)
- ;
- ; DAY NUMBER = F MOD 7 (REMAINDER OF F / 7) AND IS FIGURED AS
- ;
- ; WHERE 0 = SATURDAY, 1 = SUNDAY, ETC.
- ;
- ; NOTE: THE DAY NUMBER IS FIGURED AS (F MOD 7000) MOD 7 TO
- ; PREVENT AN OVERFLOW CAUSED BY DIVIDING A LARGE NUMBER
- ; BY A SMALL ONE.
- ;
- ; THIS PROGRAM IS MADE TO RUN AS A .COM FILE, AND MUST BE RUN THROUGH
- ; EXE2BIN.EXE IN ORDER TO OPERATE CORRECTLY
- ;
- ;****************************************************************************;
- IF1 ;DURING PASS 1
- INCLUDE ASSEMBLE.MAC ;INCLUDE MACRO LIBRARY
- ENDIF
- ;
- COLUMNS EQU 80 ;NUMBER OF COLUMNS ON SCREEN
- ;
- BDATES STRUC ;STRUCTURE FOR BINARY DATE
- MONTH DB 0 ;BYTE MONTH
- DAY DB 0 ;BYTE DAY
- YEAR DW 0 ;WORD YEAR
- BDATES ENDS
- ;
- DATETIME SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:DATETIME, DS:DATETIME, ES:DATETIME, SS:NOTHING
- ORG 100H ;SET ORIGIN TO XXXX:0100H
- ENTRY LABEL NEAR ;ENTRY POINT
- JMP CODE_START ;JUMP AROUND DATA AREAS
- DB 'CLOCK.ASM' ;COPYRIGHT NOTICE
- DB 'COPYRIGHT (C) 1983'
- DB 'JERRY D. STUCKLE'
- DB 'PUBLIC DOMAIN SOFTWARE' ;PROGRAM FOR PUBLIC DOMAIN
- CSRSAVE DW ? ;CURSOR MODE SAVE AREA
- WRKAREA DB 11 DUP (?) ;WORK AREA
- TIME DB 8 DUP (0),'$' ;AREA FOR ASCII TIME
- BDATE BDATES <,,> ;BINARY DATE AREA
- CURRDAY DB 10 DUP (?) ;AREA FOR ASCII DAY
- DATEOUT DB 20 DUP (?) ;AREA FOR ASCII DATE
- DOSERR DB 'DOS 2.0 OR ABOVE REQUIRED. PROGRAM TERMINATED.',0AH,0DH
- ;
- MO_TBL LABEL WORD ;POINTER TO MONTH NAMES
- DW OFFSET JAN ;JANUARY
- DW OFFSET FEB ;FEBRUARY
- DW OFFSET MAR ;MARCH
- DW OFFSET APR ;APRIL
- DW OFFSET MAY ;MAY
- DW OFFSET JUN ;JUNE
- DW OFFSET JUL ;JULY
- DW OFFSET AUG ;AUGUST
- DW OFFSET SEP ;SEPTEMBER
- DW OFFSET OCT ;OCTOBER
- DW OFFSET NOV ;NOVEMBER
- DW OFFSET DEC ;DECEMBER
- ; ;ASCIIZ STRINGS FO MONTH NAMES
- JAN DB 'JANUARY ',0
- FEB DB 'FEBRUARY ',0
- MAR DB 'MARCH ',0
- APR DB 'APRIL ',0
- MAY DB 'MAY ',0
- JUN DB 'JUNE ',0
- JUL DB 'JULY ',0
- AUG DB 'AUGUST ',0
- SEP DB 'SEPTEMBER ',0
- OCT DB 'OCTOBER ',0
- NOV DB 'NOVEMBER ',0
- DEC DB 'DECEMBER ',0
- ;
- ;
- DAY_NAM LABEL WORD ;POINTER TO DAY NAMES
- DW OFFSET SAT ;SATURDAY
- DW OFFSET SUN ;SUNDAY
- DW OFFSET MON ;MONDAY
- DW OFFSET TUE ;TUESDAY
- DW OFFSET WED ;WEDNESDAY
- DW OFFSET THU ;THURSDAY
- DW OFFSET FRI ;FRIDAY
- ; ;ASCIIZ STRINGS OF DAY NAMES
- SAT DB 'SATURDAY',0
- SUN DB 'SUNDAY',0
- MON DB 'MONDAY',0
- TUE DB 'TUESDAY',0
- WED DB 'WEDNESDAY',0
- THU DB 'THURSDAY',0
- FRI DB 'FRIDAY',0
- ;
- CODE_START LABEL NEAR
- ;
- ; FIRST, WE CLEAR THE SCREEN. THEN, IF NOT AT AT LEAST DOS 2.0,
- ; WE TERMINATE THE PROGRAM.
- ;
- CLS
- DOSCALL 30H ;GET DOS VERSION NUMBER
- CMP AL,2 ;AT LEAST DOS 2.0?
- JGE CONT ;YES - CONTINUE
- DISPLAY DOSERR ;NO - DISPLAY DOS ERROR MESSAGE
- INT 20H ;AND TERMINATE
- ;
- ; SAVE THE CURSOR MODE, THEN ERASE IT
- ; ALSO, SET THE CONTROL-BREAK INTERRUPT VECTOR
- ;
- CONT: ;DOS VERSION GOOD
- CURSOR SAVE,CSRSAVE ;SAVE CURSOR MODE
- CURSOR ERASE ;ERASE CURSOR
- SETINT 23H,TERMIN ;SET CNTL-BREAK VECTOR
- CALL PROCESS_DATE ;GET THE DATE
- ;
- ; DATE PROCESSING IS COMPLETE. PROCESS THE TIME
- ; NOTE: WHEN DX IS LOADED, THE 2 CHARACTERS ARE SWAPPED, SO THE
- ; COMPARE '32' IS FOR THE 23'RD HOUR.
- ;
- PROCESS_TIME:
- GETTIME WRKAREA,CHAR ;GET CURRENT TIME IN ASCII
- MOV DX,WORD PTR TIME ;GET OLD HOUR IN DH
- MOVE TIME,WRKAREA,8 ;MOVE IT INTO THE TIME FIELD
- CMP DX,WORD PTR TIME ;SAME AS NEW AREA?
- JE SHOW_TIME ;YES - NO NEED TO DISPLAY DATE
- CMP DX,'32' ;WAS IT 23:XX:XX?
- JNE SHOW_TIME ;NO - DON'T DISPLAY THE DATE
- CALL PROCESS_DATE ;DAY HAS CHANGED - DISPLAY IT
- SHOW_TIME:
- LOCATE 15,(COLUMNS-8)/2 ;LOCATE THE CURSOR
- DISPLAY TIME ;AND DISPLAY IT
- JMP PROCESS_TIME ;AND GO PROCESS THE TIME AGAIN
- ;
- ; GET THE CURRENT DATE AND PROCESS IT
- ;
- PROCESS_DATE PROC NEAR ;PROCESS DATE
- GETDATE BDATE,BIN ;GET CURRENT DATE IN BINARY
- ;
- ; F = 365 * YEAR + DAY + (31 * (MONTH - 1))
- ;
- MOV AX,BDATE.YEAR ;GET CURRENT YEAR
- SAVE AX ;SAVE ON STACK
- MOV BX,365 ;NUMBER OF DAYS IN A YEAR
- MUL BX ;MULTIPLY
- CLEAR BH ;CLEAR BH
- MOV BL,BDATE.DAY ;GET THE DAY
- ADD AX,BX ;ADD TO AX
- ADC DX,0 ;ADD ANY CARRY TO DX
- MOV WORD PTR WRKAREA,AX ;SAVE IN WORK AREA
- MOV WORD PTR WRKAREA+2,DX ;SAVE HIGH ORDER, TOO.
- CLEAR AH ;CLEAR AH
- MOV AL,BDATE.MONTH ;GET THE MONTH
- DEC AL ;DECREMENT
- MOV BL,31 ;MAX DAYS IN MONTH
- MUL BL ;MULTIPLY
- ADD WORD PTR WRKAREA,AX ;ADD TO WRKAREA
- ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
- ;NOW WE MUST USE ONE OF TWO DIFFERENT ROUTINES
- CMP BDATE.MONTH,3 ;JANUARY OR FEBRUARY?
- JGE PROCESS_DATE_2 ;NO - GO TO SECOND ROUTINE
- ;
- ; IF MONTH < 3 THEN F = F + INT ((YEAR - 1) / 4) -
- ; INT ((INT ((YEAR / 100) + 1)) * 3 / 4)
- ;
- RESTORE AX ;GET YEAR BACK
- DEC AX ;DECREMENT UEAR
- SAVE AX ;AND SAVE IT AGAIN
- SHR AX,1 ;DIVIDE BY 2...
- SHR AX,1 ;AND AGAIN.
- ADD WORD PTR WRKAREA,AX ;ADD TO WORK AREA
- ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
- RESTORE AX ;GET (YEAR-1) BACK
- MOV BL,100 ;100 TO DL
- DIV BL ;AND DIVIDE
- INC AL ;INCREMENT IT
- MOV BL,3 ;MULTIPLY BY 3...
- MUL BL ;DO IT
- SHR AX,1 ;DIVIDE BY 2...
- SHR AX,1 ;AND THEN AGAIN.
- CLEAR AH ;THROW AWAY REMAINDER
- SUB WORD PTR WRKAREA,AX ;SUBTRACT NUMBER OF LEAP DAYS
- SBB WORD PTR WRKAREA,0 ;AND ANY BORROW REQUIRED.
- JMP PROCESS_DATE_3 ;GO BACK TO COMMON ROUTINE
- PROCESS_DATE_2:
- ;
- ; IF MONTH >= 3 THEN F = F + INT ((MONTH + 23) * 4 / 10) +
- ; INT (YEAR / 4) - INT ((INT (YEAR / 100) + 1) * 3 / 4)
- ;
- MOV AL,BDATE.MONTH ;GET THE MONTH IN AL
- CLEAR AH ;CLEAR HIGH ORDER BYTE
- SHL AX,1 ;MULTIPLY BY 2...
- SHL AX,1 ;AND AGAIN BY 2
- ADD AX,23 ;ADD 23
- MOV BL,10 ;MOVE 10 TO BL
- DIV BL ;AND DIVIDE
- CLEAR AH ;THROW OUT REMAINDER
- SUB WORD PTR WRKAREA,AX ;SUBTRACT FROM WORK AREA
- SBB WORD PTR WRKAREA+2,0 ;AND SUBTRACT ANY BORROW.
- RESTORE AX ;GET YEAR BACK
- SAVE AX ;SAVE IT AGAIN
- SHR AX,1 ;DIVIDE BY 2
- SHR AX,1 ;AND DO IT AGAIN
- ADD WORD PTR WRKAREA,AX ;ADD TO WORK AREA
- ADC WORD PTR WRKAREA+2,0 ;ADD ANY CARRY
- RESTORE AX ;GET (YEAR-1) BACK
- MOV BL,100 ;100 TO DL
- DIV BL ;AND DIVIDE
- INC AL ;INCREMENT IT
- MOV BL,3 ;MULTIPLY BY 3...
- MUL BL ;DO IT
- SHR AX,1 ;DIVIDE BY 2...
- SHR AX,1 ;AND THEN AGAIN.
- CLEAR AH ;THROW AWAY REMAINDER
- SUB WORD PTR WRKAREA,AX ;SUBTRACT NUMBER OF LEAP DAYS
- SBB WORD PTR WRKAREA,0 ;AND ANY BORROW REQUIRED.
- PROCESS_DATE_3:
- ;
- ; DAY NUMBER = (F MOD 7000) MOD 7
- ;
- MOV AX,WORD PTR WRKAREA ;GET TOTAL IN AX...
- MOV DX,WORD PTR WRKAREA+2 ;AND HIGH ORDER IN DX
- MOV BX,7000 ;DIVIDE BY 7000 SO WE...
- DIV BX ;...DON'T GET AN OVERFLOW
- MOV AX,DX ;REMAINDER TO AX
- CLEAR DX ;CLEAR HIGH ORDER WORD
- MOV BX,7 ;NOW DIVIDE BY 7 IN 32...
- DIV BX ;BIT MODE SO WE DON'T OVERFLOW.
- MOV BX,DX ;GET DAY NUMBER IN BL
- SHL BX,1 ;SHIFT FOR TABLE LOOKUP
- MOV SI,WORD PTR DAY_NAM [BX] ;GET DAY NAME
- LEA DI,CURRDAY ;GET ADDRESS OF DAY AREA
- CLD ;SET INCREMENT
- ;
- ; WE HAVE THE CURRENT DAY. MOVE IT INTO THE WORK AREA AND DISPLAY
- ; IT, CENTERED. FORMULA FOR CENTERING IS (COLUMNS+1-LENGTH)/2
- ; AND IS FIGURED BY ((START ADDRESS+COLUMNS+1)-END ADDRESS)/2
- ;
- DAY_LOOP:
- MOVSB ;MOVE A BYTE
- CMP BYTE PTR [SI],0 ;END OF STRING?
- JNE DAY_LOOP ;NO - WE'RE NOT DONE
- MOV BYTE PTR [DI],'$' ;MOVE IN A '$'
- LEA BX,CURRDAY+(COLUMNS+1) ;START ADDRESS + LINE LENGTH
- SUB BX,DI ;SUBTRACE END ADDRESS
- SHR BL,1 ;AND DIVIDE BY 2
- CLS ;CLEAR THE SCEEN
- LOCATE 11,BL ;LOCAT THE CURSOR
- DISPLAY CURRDAY ;AND DISPLAY THE DAY
- ;
- ; NOW WE MUST MOVE THE CURRENT MONTH INTO THE STRING
- ;
- MOV BL,BDATE.MONTH ;GET CURRENT MONTH
- DEC BL ;DECREMENT FOR TABLE LOOKUP
- SHL BX,1 ;MULTIPLY BY 2
- MOV SI,MO_TBL[BX] ;GET ADDRESS OF MONTH NAME
- LEA DI,DATEOUT ;GET TO STRING ADDRESS
- CLD ;INCREMENT ADDRESSES
- MONTH_LOOP: ;MOVE THE MONTH NAME
- MOVSB ;NO - MOVE THE BYTE
- CMP BYTE PTR [SI],0 ;IS THE NEXT BYTE 0?
- JNE MONTH_LOOP ;AND GO CHECK THE NEXT BYTE
- ;
- ; CURRENT MONTH NAME IS READY. LET'S GET THE DAY NEXT, CONVERT IT
- ; TO ASCII, AND PUT IT IN THE STRING
- ;
- MOVE_DAY:
- MOV AL,BDATE.DAY ;GET THE DAY IN AL
- AAM ;CONVERT TO UNPACKED DECIMAL
- OR AX,3030H ;CONVERT TO ASCII
- CMP AH,'0' ;IS THE FIRST CHARACTER 0?
- JE MOVE_LOW_DATE ;YES - DO NOT MOVE IT
- MOV BYTE PTR [DI],AH ;NO - MOVE IT
- INC DI ;AND INCREMENT DESTINATION
- MOVE_LOW_DATE:
- MOV BYTE PTR [DI],AL ;MOVE IN LOW DATE
- INC DI ;POINT TO NEXT BYTE
- MOV BYTE PTR [DI],',' ;MOVE IN A COMMA
- INC DI ;POINT TO NEXT BYTE
- MOV BYTE PTR [DI],' ' ;A SPACE GOES HERE
- INC DI ;AND POINT AT NEXT BYTE
- ;
- ; DAY PROCESSING IS COMPLETE, NOW DO THE SAME TO THE YEAR
- ;
- MOV AX,BDATE.YEAR ;GET CURRENT YEAR
- SAVE DI ;SAVE DESTINATION ADDRESS
- CVD WRKAREA,BDATE.YEAR ;CONVERT THE YEAR TO ASCII
- RESTORE DI ;RESTORE DESTINATION ADDRESS
- MOVE [DI],WRKAREA,4 ;MOVE YEAR TO DESTINATION
- MOV BYTE PTR [DI],'$' ;SET A '$' AT THE END
- ;
- ; STRING IS BUILT. CENTER IT USING THE SAME EQUATION AS THE DAY.
- ;
- LEA BX,DATEOUT+COLUMNS ;START ADDRESS + LINE LENGTH
- SUB BX,DI ;SUBTRACE END ADDRESS
- SHR BX,1 ;AND DIVIDE BY 2
- LOCATE 13,BL ;LOCATE THE CURSOR
- DISPLAY DATEOUT ;AND DISPLAY THE DATE
- RET ;RETURN TO CALLER
- PROCESS_DATE ENDP
- TERMIN PROC NEAR ;TERMINATION PROCEDURE
- CURSOR SET,CSRSAVE ;RESTORE CURSOR
- CLS ;CLEAR THE SCREEN
- CLEAR AX ;RETURN CODE 0
- DOSCALL 4CH ;AND TERMINATE
- TERMIN ENDP
- DATETIME ENDS
- END ENTRY
-