Post Reply 
 
Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Reading the DOS timer
06-24-2010, 07:38 PM
Post: #1
Reading the DOS timer
Unless care is taken, TP/BP will access the longint DOS timer non-atomically, as two words. Therefore there is a chance (about once an hour) that it may be updated with an inter-word carry in between the two parts of a TP/BP access, which would lead to a one-hour error. Program ATOM046C.PAS demonstrates this (at an accelerated rate), when compiled by BP7 (but not TP5 ?!?).

Code:
{$M 4000, 0, 0}

program ATOM046C { tests access to $40:$6c } {$IFNDEF MSDOS} Fail {$ENDIF} ;

uses Dos ;

var head : word absolute $40:$1A ;
    tail : word absolute $40:$1C ;


procedure FlushKB ; begin head := tail end { TSFAQP #16 } ;


function KeyPressed : boolean { without Crt } ;
begin KeyPressed := head<>tail end ;


procedure TestProc ;
var N, S, T : longint ; Timer : longint absolute $40:$6C ;
begin N := 0 ; S := 0 ;
  repeat Inc(S) ; Timer := $0000FFFF ;
    repeat if KeyPressed then EXIT ;
      Inc(N) ; T := Timer ;
      if (T<>$0000FFFF) and (T<>$00010000) then
        Writeln('Loop # ', N,
        ', Ticks tested ', S, ', Timer read ', T, ' = fail') ;
      until T<>$0000FFFF ;
    until false ;
  end {TestProc} ;


BEGIN Writeln('ATOM046C.PAS  www.merlyn.demon.co.uk  >= 2000/02/26') ;
Writeln(' See http://www.merlyn.demon.co.uk/pas-time.htm') ;
Writeln(' Not intended for use in a Window.') ;
Writeln(' Press any key to terminate test :') ;
TestProc ;
FlushKB ;
SwapVectors ;
Exec(GetEnv('COMSPEC'), '/C TIME') ;
SwapVectors ;

{ This reads $40:$6C non-atomically when compiled with BP7
  (as Borland compiles longint access as two word accesses),
  as shown by the readings of 131071; but not shown in TP5. }

END.

32-bit Delphi does not have this problem; it does 32-bit accesses atomically.

One way to access the DOS timer atomically is with Int1A/00 - but it was intended for OS use only, and does not itself update the DayCount when required; therefore the state of the Midnight Flag in Seg0040:$0070 will be lost.

Code:
Regs.AH := 0 ; Intr($1A, Regs) ;
  with Regs do Count := longint(CX) shl 16 + DX ;

  function Tix : longint ; assembler ;
  asm  mov ah,0 ; int $1a {Get $40:$6c; but lose Midnight Flag} ;
    {$IFDEF PASCAL} mov ax,dx ; mov dx,cx ; {$ENDIF}
    {$IFDEF DELPHI} mov ax,cx ; shl eax,16 ; mov ax,dx ; {$ENDIF}
    end {Tix} ;

In Pascal, pseudo-atomic access can be done by (derived from postings by Franz Glaser and Osmo Ronkanen) :-

Code:
repeat T1 := MemL[Seg0040:$006C] until T1 = MemL[Seg0040:$006C] ;

  function Tix : longint ; assembler ;
  asm  mov ax,$40 ; mov es,ax ;
    @1: mov ax,[es:$6c] ; mov dx,[es:$6e] ; cmp ax,[es:$6c] ; jne @1
      end {Tix} ;
which ensure that the reading was not broken by a change.

One might also force 32-bit access; but that requires better than the x86 instruction set, limiting its usefulness :-

Code:
function Tix : longint ; assembler ;
  asm  mov ax,$40 ; mov es,ax ;
    db $66 ; mov ax,[es:$6c] ; ... ?
      end {Tix} ;

See the current LONGCALC, at "Tix" and "Mls", for my present favorite Pascal and Delphi code; also NOWMINUS, which has

Code:
GetDate(Y, M, D, DoW) ;
  repeat X := DoW ;
    GetTime(Hr, Mi, Sc, Cs) ; GetDate(Y, M, D, Dow) until DoW=X ;

(in attachment).

Original version of this very usefull and interesting theme for pascal programmers is here.


Attached File(s)
.txt  longcalc.txt (Size: 101.74 KB / Downloads: 0)
.txt  nowminus.txt (Size: 16.36 KB / Downloads: 0)

Read rules Smile
[Image: legislator.png]
Find all posts by this user
Quote this message in a reply
06-24-2010, 07:40 PM (This post was last modified: 06-24-2010 07:43 PM by l3g1sl4tor.)
Post: #2
RE: Reading the DOS timer
And TBH, I used this just once, I usually just use TIME DoS function (for getting time), but it is also handy to know how to manage with timer Smile

Read rules Smile
[Image: legislator.png]
Find all posts by this user
Quote this message in a reply
06-26-2010, 06:07 AM
Post: #3
RE: Reading the DOS timer
Great job! Big Grin I'll save this for later use.

"Character is determined more by the lack of certain experiences than by those one has had."
Friedrich Nietzsche
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Forum Jump:


 Quick Theme: