On 26 Mar 1998 08:50:35 GMT, ne...@nlr.nl (nelis w.j.m.) wrote:
Hi Win,
First of all, the 'original' Borland source code for GetTime(), and
SetTime():
PROCEDURE GetTime(VAR Hour,Minute,Second,Sec100:WORD); ASSEMBLER;
{GetTime returns the current time set in the operating system.
Ranges of the values returned are: Hour 0-23, Minute 0-59,
Second 0-59 and Sec100 (hundredths of seconds) 0-99.}
ASM
MOV AH,2CH
INT 21H
XOR AH,AH
MOV AL,DL
LES DI,Sec100
STOSW
MOV AL,DH
LES DI,Second
STOSW
MOV AL,CL
LES DI,Minute
STOSW
MOV AL,CH
LES DI,Hour
STOSW
END; {GetTime}
PROCEDURE SetTime(Hour,Minute,Second,Sec100:WORD); ASSEMBLER;
{SetTime sets the time in the operating system. Valid
parameter ranges are: Hour 0-23, Minute 0-59, Second 0-59 and
Sec100 (hundredths of seconds) 0-99. If the time is not
valid, the function call is ignored.}
ASM
MOV CH, BYTE PTR Hour
MOV CL, BYTE PTR Minute
MOV DH, BYTE PTR Second
MOV DL, BYTE PTR Sec100
MOV AH,2DH
INT 21H
END; {SetTime}
As you can see here, your compiler has little to do with the strange
behaviour of your program. All it does is give you access to two BIOS
calls. Let's take a closer look at these BIOS calls, there is nowadays
quite a lot of information available about them.
These bios calls use these two memory locations when the 'time of the
day' is present:
MemW[$0040:$006E]; {most significant word}
MemW[$0040:$006C]; {least significant word}
In short; there is a LONGINT there counting how many interrupts the
Intel 8253 programmable interval timer has generated since midnight
(00:00). The 8253 updates this LONGINT at a rate of about 18.21 Hz.
From this it is clear that the BIOS calls will have to convert the
four register values which represent time into this one LONGINT for
SetTime(), and visa-versa for GetTime().
You can now almost guess what the problem is; the forward conversion
is not exactly the reverse function of the backward conversion. This
is quite tolerable because 1 tick only represent about 55 ms, and
human beings simply aren't able to detect such small differences in
time. In general this could be called 'a rounding off error' in the
BIOS, though I wouldn't call it an error. The main reason for this
behaviour is probably the higher efficiency of the algorithms now
involved.
My advise; don't use GetTime() and SetTime() repeatedly like you did,
they were not designed for that purpose. If you need to access the
timer often you should use the given memory locations and write your
own conversion routines.
If you want to estimated the drift of the 8253 timer you will need to
access something that is independent from the Intel 8248 main clock
generator because the 8253's clock pulse comes from this chip. In each
AT there's a real-time clock (RTC; MC 146818) chip which does indeed
run independently of the 8248. You can find information on how to
access this RTC on the web. The question remains of course where the
drift occurs; in the 8253 or in the MC 146818. It's highly likely that
they both drift.
Peter de Jong
wpdej...@worldonline.nl
(PS: note that the chips I mention probably aren't present in your
computer, but because the PC design is backward compatible you can act
as if they were)
Quote
>I'm working on a simple program to estimate the error in the time of the
>PC clock based on the measured drift of the clock time, and adjust the
>time accordingly. In the first tests I found that SetTime/GetTime behave
>unexpectedly (at least for me). I used the following test program (TP
>7.0, DOS 6.2):
>program test ;
>uses DOS ;
>var
> Hour , Minute , Second , Sec100 : Word ;
> NHour, NMinute, NSecond, NSec100: Word ;
> NLess, NMore: Integer ;
> I: Integer ;
>begin
> NLess:= 0 ;
> NMore:= 0 ;
> for I:= 0 to 9999 do
> begin
> GetTime( Hour, Minute, Second, Sec100 ) ;
> SetTime( Hour, Minute, Second, Sec100 ) ; { Should be a no-op? }
> GetTime( NHour, NMinute, NSecond, NSec100 ) ;
> if NSecond = Second then
> if NSec100 < Sec100 then
> Inc( NLess )
> else
> Inc( NMore ) ;
> end ; { of for }
> WriteLn( NLess, ' ', NMore ) ;
>end.
>In most of the tests, NLess will be about 9500. I would expect NLess to
>be zero! As a result of running this program, the clock will be set back
>for about 9 minutes.
>Can anyone comment on this behaviour of SetTime?
>Regards,
> Wim Nelis.