unit timer_dw; interface function GetTimer_1:dword; {счетчик в 1 мкс (0,5 ч.)} function GetTimer_50:dword; {счетчик в 50 мкс (1 сут.)} function GetTimer_1000:dword; {счетчик в 1 мс (20 сут.) } function GetCPUtick:int64; {счетчик в тактах проц. } function GetCPUfreq:dword; {частота процессора в кГц} function GetDelta:dword; {погрешность частоты в кГц } procedure InitTimer; {реинициализация таймера} implementation uses WinDos; var b1,b50,b1000,delta : longint; {коэффициенты деления} C1,c50,c1000 : longint; {маски} function GetCPUfreq:dword; {частота процессора в кГц} begin GetCPUfreq := b1000; end; function GetDelta:dword; {погрешность частоты в кГц } begin GetDelta := delta; end; function GetTimer_1:dword; assembler; asm db $0f,$31 {rdtsc} and edx,c1 div b1 end; function GetTimer_50:dword; assembler; asm db $0f,$31 {rdtsc} and edx,c50 div b50 end; function GetTimer_1000:dword; assembler; asm db $0f,$31 {rdtsc} and edx,c1000 div b1000 end; function GetCPUtick:int64; var q : int64; begin asm db $0f,$31 {rdtsc} mov dword ptr [q],eax mov dword ptr [q+4],edx end; getCPUtick := q; end; function GetLessFF(n:longint):longint;{возвращение бинарное} {число вида 00...0011...11 меньшее заданного} var i,j : longint; begin j := 1; repeat i := j; j := j*2; until j > n; GetLessFF := i-1; end; procedure InitTimer; const n = 8; {количество измерений} Const1 : extended = 0.0182; {част.стнд.таймера в кГц} var i,j : longint; t : array[0..n]of extended; {результаты измерения тактов} d : array[0..n]of extended; {результаты измерения времени, мс} t0,t1 : extended; h_,m_,s_,d_,d1_ : word; {для определения времени} sti,sta : extended; {сумма тиков; сумма тактов} begin t0 := getCPUtick; sti := 0; for i := 0 to n do begin {формируем массив измерений} GetTime(h_,m_,s_,d_); repeat GetTime(h_,m_,s_,d1_); until d1_ <> d_; t[i] := getCPUtick-t0; if d1_ > d_ then d[i] := (d1_-d_)*10 else d[i] := ((d1_+100)-d_)*10; sti := sti + d[i]; end; sti := sti - d[0]; {время измерения в мс} sta := t[n] - t[0]; {время измерения в тактах} if ((n/sti*0.8) > Const1) or { если Const1 } ((n/sti*1.2) < Const1) then { отличается } Const1 := n/sti; { более 20% } for i := 0 to n-1 do begin {вычисляем за 1 тик} t[i] := (t[i+1]-t[i]); end; for i := 1 to n-1 do {сортируем массив} for j := n-1 downto i do if t[j] < t[j-1] then begin t0 := t[j]; t[j] := t[j-1]; t[j-1] := t0; end; j := n div 4; {отбрасываем ~ по 1/4 с каждой стороны} t0 := 0; for i := j to n-1-j do { берем середину } t0 := t0 + t[i]; { отсортированного массива } t0 := t0 / (n-j-j); {ср.кол-во тактов за тик} t1 := t0 * Const1; {ср.кол-во тактов за мс} b1000 := round(t1); { вычисляем } b50 := round(t1 / 20); { коэффициенты } b1 := round(t1 / 1000); { деления } c1 := GetLessFF( b1); { вычисляем } c50 := GetLessFF( b50); { значения } c1000 := GetLessFF(b1000); { маски } t1 := 0; for i := j to n-1-j do { оцениваем } t1 := t1 + sqr(t[i]-t0); {погрешность} delta := round(sqrt(t1/(n-j-j))*Const1);{ измерения } end; begin InitTimer; end.