137 lines
4.3 KiB
NASM
137 lines
4.3 KiB
NASM
CGROUP GROUP VECTOR,CODESEG
|
|
VECTOR SEGMENT AT 0H
|
|
DB 6CH DUP(?) ;FILLER
|
|
TIME_LO DW ? ;DOS TIME
|
|
TIME_HI DW ? ;DOS TIME
|
|
VEC_IP DW ;CLOCK UPDATE VECTOR IP
|
|
VEC_CS DW ;CLOCK UPDATE VECTOR CS
|
|
VECTOR ENDS
|
|
|
|
CODESEG SEGMENT PARA
|
|
ASSUME CS:CODESEG,DS:CGROUP
|
|
ORG 100H
|
|
CLK PROC FAR
|
|
JMP SETUP ;ATTACH TO DOS
|
|
INTRPT LABEL DWORD
|
|
INT_IP DW 0 ;OLD UPDATE VECTOR IP
|
|
INT_CS DW 0 ;OLD UPDATE VECROR CS
|
|
TICKS DW 0 ;TICK COUNTER
|
|
SCR_OFF DB 0,0 ;SCREEN OFFSET IN BUFFER
|
|
CRT_PORT DW 0 ;SCREEN STATUS PORT
|
|
flag db 0
|
|
TIME DB 8 DUP(':',0BH) ;TIME SAVE AREA
|
|
CLK_INT LABEL NEAR
|
|
PUSH AX ;SAVE REGISTERS
|
|
PUSH CX
|
|
PUSH DI
|
|
PUSH SI
|
|
PUSH DS
|
|
PUSH ES
|
|
PUSHF ; AND FLAGS
|
|
CALL CS:[INTRPT] ;DO OLD UPDATE INTERRUPT
|
|
MOV CX,0040H ;GET SEGMENT OF DOS TABLE
|
|
MOV DS,CX ;PUT IN DS
|
|
MOV CX,CS:TICKS ;GET TICK COUNT
|
|
INC CX ;INCREMENT IT
|
|
CMP CX,20 ;01F4H ;HAS A MINUTE GONE BY?
|
|
JB NO_MINUTE ;NO, MOVE ON
|
|
CALL UPDATE ;YES, UPDATE CLOCK AND
|
|
MOV CX,0 ; RESET TICK COUNTER
|
|
NO_MINUTE:
|
|
MOV CS:TICKS,CX ;SAVE UPDATED TICK COUNT
|
|
MOV CX,0B000H ;GET VIDEO SEGMENT
|
|
MOV ES,CX ;PUT IN ES
|
|
MOV DX,CS:CRT_PORT ;GET CRT STATUS PORT ADDR
|
|
MOV DI,WORD PTR CS:SCR_OFF ;GET SCREEN BUFFER OFFSET
|
|
LEA SI,CS:TIME ;GET DOS TIME
|
|
MOV CX,16 ;SET UP TO MOVE 10 BYTES
|
|
CLI ;DISABLE OTHER INTERRUPTS
|
|
WAIT1: IN AL,DX ;READ CRT STATUS
|
|
TEST AL,1 ;CHECK FOR VERTICAL RETRACE
|
|
JNZ WAIT1 ;WAIT FOR RETRACE LOW
|
|
MOV AH,CS:[SI] ;GET FIRST BYTE TO MOVE
|
|
WAIT2: IN AL,DX ;GET CRT STATUS
|
|
TEST AL,1 ;CHECK FOR VERTICAL RETRACE
|
|
JZ WAIT2 ;WAIT FOR RETRACE HIGH
|
|
MOV ES:[DI],AH ;MOVE BYTE TO SCREEN
|
|
INC DI ;INCREMENT INDEX
|
|
INC SI
|
|
LOOP WAIT1 ;MOVE NEXT BYTE
|
|
STI ;ENABLE INTERRUPTS
|
|
POP ES ;RESTORE REGISTERS
|
|
POP DS
|
|
POP SI
|
|
POP DI
|
|
POP CX
|
|
POP AX
|
|
IRET ;RETURN FROM INTERRUPT
|
|
CLK ENDP
|
|
UPDATE PROC NEAR
|
|
PUSH AX ;SAVE REGISTERS
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH DS
|
|
MOV AX,0040H ;GET ADDRESS OF DOS TABLE
|
|
MOV DS,AX ;PUT IN DS
|
|
MOV AX,TIME_HI ;GET HIGH BYTE OF DOS TIME
|
|
mov flag,0 ;am flag
|
|
HOUR: CMP AX,0CH ;CONVERT TO HOURS
|
|
JLE H1
|
|
mov flag,1 ;set to pm
|
|
SUB AX,0CH
|
|
JMP HOUR
|
|
H1: AAM ;CONVERT TO ASCII
|
|
ADD AX,3030H
|
|
LEA BX,CS:TIME ;GET ADDRESS OF TIME AREA
|
|
MOV CS:[BX],AH ;SAVE HOURS FIRST DIGIT
|
|
MOV CS:[BX+2],AL ;SAVE HOURS SECOND DIGIT
|
|
MOV AX,TIME_LO ;GET DOS TIME LOW BYTE
|
|
MOV CX,8H ;CONVERT TO MINUTES
|
|
SHR AX,CL
|
|
MOV DX,3CH
|
|
MUL DL
|
|
SHR AX,CL
|
|
AAM ;CONVERT TO ASCII
|
|
ADD AX,3030H
|
|
MOV CS:[BX+6],AH ;SAVE MINUTES FIRST DIGIT
|
|
MOV CS:[BX+8],AL ;SAVE MINUTES SECOND DIGIT
|
|
mov byte ptr cs:[bx+12],'a'
|
|
cmp flag,0 ;is it am?
|
|
jz goahead
|
|
mov byte ptr cs:[bx+12],'p'
|
|
goahead:
|
|
mov byte ptr cs:[bx+14],'m'
|
|
POP DS ;RESTORE REGISTERS
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
UPDATE ENDP
|
|
SETUP: MOV AX,0 ;GET ADDRESS OF VECTOR TABLE
|
|
MOV DS,AX ;PUT IN DS
|
|
CLI ;DISABLE FURTHER INTERRUPTS
|
|
MOV AX,[VEC_IP] ;GET ADDRESS OF OLD UPDATE IP
|
|
MOV CS:[INT_IP],AX ;SAVE IT
|
|
MOV AX,[VEC_CS] ;GET ADDRESS OF OLD UPDATE CS
|
|
MOV CS:[INT_CS],AX ;SAVE IT
|
|
MOV VEC_IP,OFFSET CLK_INT ;PUT ADDRESS OF CLK IN VECTOR IP
|
|
MOV VEC_CS,CS ;PUT CS OF CLK IN VECTOR CS
|
|
STI ;ENABLE INTERRUPTS
|
|
MOV AH,0FH ;READ VIDEO STATUS
|
|
INT 10H
|
|
SUB AH,8 ;SUBTRACT 8 CHAR TIME FROM NCOLS
|
|
SHL AH,1 ;MULTIPLY BY 2 FOR ATTRIBUTE
|
|
MOV CS:SCR_OFF,AH ;SAVE SCREEN TIME LOCATION
|
|
MOV WORD PTR CS:CRT_PORT,03BAH ;SAVE MONO STATUS PORT ADDR
|
|
TEST AL,4 ;CHECK FOR COLOR MONITOR
|
|
JNZ MONO ;IF MONO, MOVE ON
|
|
ADD WORD PTR CS:SCR_OFF,8000H ;ADD COLOR OFFSET TO TIME OFFSET
|
|
MOV WORD PTR CS:CRT_PORT,03DAH ;SAVE COLOR STATUS PORT ADDR
|
|
MONO: CALL UPDATE ;DO FIRST UPDATE & PRINT TIME
|
|
MOV DX,OFFSET SETUP ;GET END ADDRESS OF NEW INTERRUPT
|
|
INT 27H ;TERMINATE AND REMAIN RESIDENT
|
|
DB 117 DUP(0) ;FILLER
|
|
CODESEG ENDS
|
|
END CLK |