Hi, I wasn't sure exactly what you wanted so I whipped up the 976uS interrupt. This is NOT exactly 1MS frequency, however it is pretty close. If you are only timing intervals you can multiply the time values by 1000/976 to convert to MS. I don't know if you can get any closer to 1MS with the PC clocks or not, if you want me to do the math let me know. This program takes over the clock while it is enabled; the clock will keep time but any TSR that uses the clock interrupts will be disabled until you call the power-down routine. To use this program you have to call an initialize routine during your startup code which will hook the interrupt and turn on the timer. Then you can read the time whenever you want; when you are getting ready to exit your program you have to call the power-down routine to unhook the interrupt and reset the clock interrupt system to its original state. More detail can be found in the code comments. ; ; periodic.asm ; ; Turns the periodic clock timer on at a frequency of 976 uS. ; This is 3.4% different from an exact 1 MS clock ; ; multiply by 1000/976 to get elapsed MS more accurately ; ; I gave the major functions C names in case you want to call from C. ; I think you want to call from assembler though? ; ; To use this: ; ; at program start call _mstime_pup. This chains in the interrupt ; and turns it on. ; ; run the rest of your program. Any time you want to know the number ; of ticks ; that has gone by read _lowtime and _hightime. _hightime is the high ; 16 bits, _lowtime is the low sixteen bits... this allows you to time ; up to 4G ticks. If you need longer times just add another word into ; the data seg and the interrupt. ; Alternately you can call _mstime_rettime to get the time returned ; in DX:AX ; ; at program end call _mstime_down. This will unchain the interrupt ; and return the clock to its previous state. This is a well-behaved ; program... it takes over the clock while it is running but resets ; the clock the way it was when it is done. Other programs that use ; the clock interrupt will be disabled while this is running, and re-enabled ; when this is done. ; ; ; To use this program as a seperate module, remove the .stack directive ; and change the end statement. Make sure when you call these routines ; or use the variables that your ds reg is set to this data segment. ; ; Programmer: ; David Lindauer e-mail: gclind01@ulkyvx ; July 19,1995 ; ; ; .MODEL small .STACK PUBLIC _mstime_down, _mstime_pup, _lowtime, _hightime PUBLIC _mstime_rettime ; ; Interrupts we use ; DOSINT = 21h ; Dos interrupt TIMERINT = 70h ; Clock interrupt ; ; Dos int commands ; GETINT = 035h ; Dos command to get an int SETINT = 025h ; Dos command to set an int ; ; Port addresses ; CMOSADDRESS = 070h ; CMOS address reg CMOSDATA = 071h ; CMOS data reg PIC0CONTROL = 20h ; PIC 0 control reg PIC1CONTROL = 0a0h ; PIC 1 control reg PIC1ENABLE = 0A1h ; PIC 1 enable reg ; ; End of interrupt command for pic ; NSEOI = 20h ; Non-specific end of interrupt command ; ; Clock status registers ; SRA = 0ah ; Status reg A SRB = 0bh ; Status reg B SRC = 0Ch ; Status reg C SRD = 0Dh ; Status reg D ; ; Masks and states for clock control ; DIVIDERCONTROL = 026h ; Set the timer to 0.976 ms PERIODICINT = 040h ; Periodic timer interrupt enable TIMERMASK = 1 ; Bit for PIC 1 enable UPDATEINPROGRESS = 080h ; Test for update in progress NOINTS = 08fh ; Mask to turn off all clock ints NMIBIT = 80h ; Bit to turn off NMI in CMOS commands ; ; IO Delays ; IODELAY MACRO jmp $+2 jmp $+2 endm .data _lowtime dw 0 ; low 16 bits of time value _hightime dw 0 ; high 16 bits of time value oldint70 dd 0 ; Value int 70h had originally oldregA db 0 ; Save for SRA oldregB db 0 ; Save for SRB oldpic db 0 ; Save for PIC enable .code ; ; Wait for update ; AwaitUpdate PROC mov dl,2 mov cx,0000h ; This long at max awaitUpdate2: mov al,SRA ; Read SRA call ReadCMOSwithNoNMI ; test ax,UPDATEINPROGRESS ; Check the update bit loopnz awaitUpdate2 ; Loop while waiting dec dl jnz awaitUpdate2 ret AwaitUpdate ENDP ; ; Read CMOS ; ReadCMOS PROC cli ; No interrupts out CMOSADDRESS,al ; Send address IODELAY ; IO Delay in al,CMOSDATA ; Read data sti ; Interrupts ret ; ReadCMOS ENDP ; ; Write CMOS ; WriteCMOS PROC cli ; No interrupts out CMOSADDRESS,al ; Out address IODELAY mov al,ah ; Write data out CMOSDATA,al ; sti ; Let interrupts ret WriteCMOS ENDP ; ; Read CMOS with NMI disabled ; ReadCMOSwithNoNMI PROC or al,NMIBIT ; Set NMI bit call ReadCMOS ; Read CMOS OnNMI: push ax ; Save results mov al,SRD ; Read SRD with no NMI disable call ReadCMOS ; pop ax ; ret ReadCMOSwithNoNMI ENDP ; ; Write CMOS with NMI disabled ; WriteCMOSwithNoNMI PROC or al,NMIBIT ; Set NMI bit call WriteCMOS ; Write the data jmp short onNMI ; Go enable NMI WriteCMOSwithNoNMI ENDP ; ; Timer Power up routine ; _mstime_pup proc mov ah,GETINT ; Get the original value of int 70h mov al,TIMERINT ; So we can restore it later int DOSINT ; mov [word ptr oldint70],bx ; mov [word ptr oldint70+2],es; push ds ; Now set the new value of int 70h mov ah,SETINT ; mov al,TIMERINT ; push cs ; pop ds ; mov dx,offset mstime_int ; int DOSINT ; pop ds ; call AwaitUpdate ; Wait for update to complete mov al,SRA ; Set up the divider for .976uS call ReadCMOSwithNoNMI ; mov [oldregA],al mov ah,DIVIDERCONTROL ; mov al,SRA call WriteCMOSwithNoNMI ; mov al,SRB ; Set the periodic int flag call ReadCMOSwithNoNMI ; mov [oldregB],al and al,NOINTS or al,PERIODICINT ; xchg ah,al ; mov al,SRB ; call WriteCMOSwithNoNMI ; in al,PIC1ENABLE ; Enable the interrupt at the PIC mov [oldpic],al and al,NOT TIMERMASK ; out PIC1ENABLE,al ; ret _mstime_pup endp ; ; Timer Power down routine ; _mstime_down proc mov ah,[oldregA] ; Reset timer reg A mov al,SRA ; call WriteCMOSwithNoNMI ; mov ah,[oldregB] ; Reset timer reg B mov al,SRB ; call WriteCMOSwithNoNMI ; mov al,[oldpic] ; Reset the PIC the way it was out PIC1ENABLE,al ; push ds ; Now set the original value of int 70h mov ah,SETINT ; mov al,TIMERINT lds dx,oldint70 ; int DOSINT ; pop ds ; ret _mstime_down endp ; ; Return elapsed time ; _mstime_rettime proc mov ax,[_lowtime] mov dx,[_hightime] ret _mstime_rettime endp ; ; Timer interrupt. Executed every 976 uS ; mstime_int proc sti ; Enable ints push ds ; Get our DGROUP push ax ; mov ax,DGROUP ; mov ds,ax ; inc _lowtime ; Inc low counter jnz outint ; Get out if nz inc _hightime ; Inc high counter outint: mov al,SRC ; Read status reg C to clear flags call ReadCMOSwithNoNMI ; mov al,NSEOI ; Acknowledge the int out PIC1CONTROL,al ; IODELAY out PIC0CONTROL,al ; pop ax pop ds iret mstime_int endp ; ; Test routine. Initializes timer, waits for a keypress, turns timer off ; mstime_test proc mov ax,DGROUP mov ds,ax call _mstime_pup sub ah,ah int 16h call _mstime_down mov ah,4ch int 21h mstime_test endp end mstime_test