{ > I would like to include a clock in my current project which will be > updated once a minute. Instead of constantly checking the computer's clock > and waiting for it to change, I would like to use an interrupt. This one has even a hot key handler. If you want to update it once per minute, bump a counter within the interrupt 1Ch handler till it reaches the value 60*18.2. Then refresh the screen. } Program Clock; {$G+,R-,S-,M 1024, 0, 0 } uses Dos; Const x = 71; { x location on screen } y = 1; { y location on screen } Keyboard = 9; { Hardware keyboard interrupt } TimerTick = $1C; { Gets called 18.2 / second } VideoOffset = 160 * (y - 1) + 2 * x;{ Offset in display memory } yellow = 14; blue = 1; attribute = blue * 16 + yellow; { Clock colours } VideoBase : Word = $B800; { Segment of display memory } ActiveFlag : ShortInt = -1; { 0: on, -1: off } Var OrgInt9, { Saved interrupt 9 vector } OrgInt1Ch : Pointer; { Saved interrupt 1Ch vector } VideoMode : Byte absolute $0000:$0449; { Display a string using Dos services (avoid WriteLn, save memory) } Procedure DisplayString(s : String); Assembler; ASM PUSH DS XOR CX, CX LDS SI, s LODSB MOV CL, AL JCXZ @EmptyString CLD @NextChar: LODSB XCHG AX, DX MOV AH, 2 INT 21h LOOP @NextChar @EmptyString: POP DS end; { Returns True if a real time clock could be found } Function HasRTClock : Boolean; Assembler; ASM XOR AL, AL MOV AH, 2 INT 1Ah JC @NoRTClock INC AX @NoRTCLock: end; { Release Dos environment } Procedure ReleaseEnvironment; Assembler; ASM MOV ES, [PrefixSeg] MOV ES, ES:[002Ch] MOV AH, 49h INT 21h end; { INT 9 handler intercepting Alt-F11 } Procedure ToggleClock; Interrupt; Assembler; Const F11 = $57; { 'F11' make code } BiosSeg = $40; { Segment of BIOS data area } AltMask = $08; { Bitmask of Alt key } KbdFlags = $17; { Byte showing keyboard status } ASM STI IN AL, 60h { F11 pressed? } CMP AL, F11 JNE @PassThru { Alt-key pressed? } PUSH BiosSeg POP ES MOV AL, ES:[KbdFlags] AND AL, AltMask CMP AL, AltMask JNE @PassThru { Flip status flag, force EOI and leave routine } NOT [ActiveFlag] IN AL, 61h MOV AH, AL OR AL, 80h OUT 61h, AL MOV AL, AH OUT 61h, AL CLI MOV AL, 20h OUT 20h, AL STI JMP @Exit @PassThru: CLI PUSHF CALL DWord Ptr [OrgInt9] @Exit: end; { ToggleClock } { Convert a packed BCD byte to ASCII character } Procedure Digit; Assembler; ASM PUSH AX CALL @HiNibble POP AX CALL @LoNibble RETN @HiNibble: SHR AL, 4 JMP @MakeAscii @LoNibble: AND AL, 0Fh @MakeAscii: OR AL, '0' STOSW end; { INT 1Ch handler that displays a clock on the right hand side of the screen } Procedure DisplayClock; Interrupt; Assembler; ASM CMP [ActiveFlag], 0 JNE @Exit CLD MOV AH, 2 INT 1Ah MOV ES, [VideoBase] MOV DI, VideoOffset MOV AH, attribute MOV AL, CH CALL Digit MOV AL, ':' STOSW MOV AL, CL CALL Digit MOV AL, ':' STOSW MOV AL, DH CALL Digit PUSHF CALL DWord Ptr [OrgInt1Ch] @Exit: end; Begin If VideoMode = 7 Then VideoBase := $B000; GetIntVec(TimerTick, OrgInt1Ch); SetIntVec(TimerTick, @DisplayClock); GetIntVec(Keyboard, OrgInt9); SetIntVec(Keyboard, @ToggleClock); SwapVectors; ReleaseEnvironment; DisplayString('CLOCK installed. toggles on/off'); Keep(0); end.