Немного теории:
Многие программист С++/Delphi часто задавались вопросом определения частоты процессор, это может понадобится например для выскоточных пауз независимых от частоты процессора(для того и нужно определить частоту что б сделать нужно количество команд, которое будет выполнятся на всех процессорах одинаково количество времени).
У процессора много разных интересных железных штук есть и вот одна из них это TSC - TimeStampCounter. Счетчик сумарно выполненых тактов с последнего ресета процессора. Он представляет собой Квад-слово или 8 байт. Внимание:Нижние четыре байта - прямой источник псевдо-случайных чисел в большинстве алгоритмов рандома! Прочесть значение этих 8 байт можно командой RDTSC. У этой команды нет ни аргументо и даже ложить в регистры ничего не надо, перед вызовом. Вызываем и в регстрах EDX:EAX(Верхние 4 байта в EDX, нижние 4 байта в EAX) оказывается текущее значение TSC. На заметку: счетчик этот так же позволяет посчитать сумарное количество секунд аптайма компьютера. Иными словами - сколько он находился без перезагрузки. TSC/Частота проца = время аптайма.
Пример реализации:
rdtsc ;Считываем текущее значение TSC.
mov [timerLo],eax ;Помещаем текущее значение TSC
mov [timerHi],edx ;в переменные.
invoke Sleep,100 ;Ждем 100 милисекунд.
rdtsc ;Опять считываем уже новое значение TSC.
sub eax,[timerLo] ;Вычитаем из него предыдущее.
sbb edx,[timerHi] ;значение.
mov ecx,10 ;интервал 100 милисекунд - надо умножить
mul ecx ;на 10 что бы получить сколько происходит
; тактов за секунду. 1000 милисек = 1 сек.
timerLo и timerHi это DWORD-ы. Синтаксис FASM.
Вот таким простым образом мы узнали частоту процессора. Погрешности конечно могут быть и даже будут, но они несущественные.
Как ни странно но определить марку и модель процессора еще проще чем частоту. Всю информацию нам предоставит команда CPUID. В EAX нужно поместить код нужных данных(все они вшиты в ROM процессора.). Нас интересует функция 80000002h 80000003h и 80000004h. Эта команда возвращает данные во все регистры общего назначения - EAX EBX ECX EDX, причем именно в такой последовательности.
brand - это массив байт заданный вот так:
brand db 80 dup(0)
Все три функции(80000002h , 80000003h и 80000004h) возвращают разные части одной общей строки в которой содержится основная информация о процессоре. Для примера вот мое тестовое приложение:
[Ссылки могут видеть только зарегистрированные пользователи. ] Приложу весь проект: [Ссылки могут видеть только зарегистрированные пользователи. ]
Последний раз редактировалось Ivan_32; 25.03.2009 в 05:20.
Re: Определяем частоту процессора, марку и модель.
Пока не забыл напишу - это на самом деле не самый точный способ и он совсем не подходит в некоторых случаях Например когда частота проца более 4.2 Ггц, потому все умные люди задействуют в этом вычислении FPU.
timer dq 0.0
temp dq 0.0
rdtsc
mov dword[timer],edx
mov dword[timer+4],eax
fild qword [timer]
fstp qword[timer] ; Самый простой способ конвертации из обычного числа в IEEE754
invoke Sleep(100)
mov dword[temp],edx
mov dword[temp],eax ; Как ни крути а грузить переменные в FPU можно только из памяти, обломно ниче не скажешь...
; Правда можно их просто в стек пихнуть на время, а потом его выровнять как все закончится
fild qword[temp]
fsub qword[timer]
push dword 10.0 ; немного уличной магии=)
fmul dword[esp]
fistp qword[timer]
Конечно размерность вывода значения не имеет - dword qword - неважно, главное что бы значение вместилось в него. Кстати, для тех кто не знает как можно работать с 64-битными целыми числами в 32-битном защищенном режиме - MMX.
Он конечно запилит FPU на время вычислений и запилит весь его стек скорее всего, но зато он умеет делать и SIMD вычисления, так что сей алгоритм можно и оптимизировать, тем более сейчас уже есть SSE - от FPU он не зависит, в отличие от MMX который просто использует 64-битные части FPU-регистров. Ну а для людей ленивых(вроде меня) я бы порекомендовал использовать функции семейства sprintf из MSVCRT.DLL или CRTDLL.DLL. Они там почти аналогичные - главное ни в коем случае не юзайте для этих целей NTDLL.DLL - С-функции в ней сугубо корявые и совсем не винрарные=)