谁来跟我一起讨论关于CPU主频的正确获取(200分)

  • 主题发起人 主题发起人 weiliu
  • 开始时间 开始时间
W

weiliu

Unregistered / Unconfirmed
GUEST, unregistred user!
大家都知道,CPU主频可以通过下列方式获取:
function CPUSpeed: Double;
const
DelayTime = 500;
var
TimerHi, TimerLo: DWORD;
PriorityClass, Priority: Integer;
begin
PriorityClass := GetPriorityClass(GetCurrentProcess);
Priority := GetThreadPriority(GetCurrentThread);
SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
Sleep(10);
asm
dw 310Fh
mov TimerLo, eax
mov TimerHi, edx
end;
Sleep(DelayTime);
asm
dw 310Fh
sub eax, TimerLo
sbb edx, TimerHi
mov TimerLo, eax
mov TimerHi, edx
end;
SetThreadPriority(GetCurrentThread, Priority);
SetPriorityClass(GetCurrentProcess, PriorityClass);
Result := TimerLo / (1000.0 * DelayTime);
end;
现在问题是这样的,这样的获取方式,一般台式机的CPU问题不大,但在笔记本机器上,比如PM/CM/及AMD的移动处理器上就经常不准,还有,新鲜出炉的扣肉处理器也有时会测不准,但是同样新版的CPU-Z就能拿到准确的频率,大家从实际编程的角度出发看看如何能正确拿到CPU的主频。我想通过获得CPU目前的外频和倍频再来得出的话可能会准确点,但具体怎么做,大家谁有经验的?
 
汇编代码在不同cpu的机器上,指令长度肯定不一样,这就是一个不准确的原因。
 
为什么笔记本不同
 
cqwty,
这个跟指令长度有关系吗?
能具体解释一下吗?
 
分析一下 CPU-Z 的代码不就知道了吗
 
你查一下那个TICKCOUNT()相似的那个函数,就知道了,就是提取计算机主频的
里面有什么"temp"什么的,也是个函数
 
begin
asm //execute the extended CPUID inst.
mov eax,$80000000 //sub. func call
db $0F,$A2
mov _eax,eax
end;
if _eax > $80000000 then //any other sub. funct avail. ?
begin
asm //get brand ID
mov eax,$80000002
db $0F
db $A2
mov _eax,eax
mov _ebx,ebx
mov _ecx,ecx
mov _edx,edx
end;
s := '';
s1 := '';
s2 := '';
s3 := '';
for i := 0 to 3 do
begin
b := lo(_eax);
s3:= s3 + chr(b);
b := lo(_ebx);
s := s + chr(b);
b := lo(_ecx);
s1 := s1 + chr(b);
b := lo(_edx);
s2 := s2 + chr(b);
_eax := _eax shr 8;
_ebx := _ebx shr 8;
_ecx := _ecx shr 8;
_edx := _edx shr 8;
end;
s_all := trim(s3 + s + s1 + s2);
asm
mov eax,$80000003
db $0F
db $A2
mov _eax,eax
mov _ebx,ebx
mov _ecx,ecx
mov _edx,edx
end;
s := '';
s1 := '';
s2 := '';
s3 := '';
for i := 0 to 3 do
begin
b := lo(_eax);
s3 := s3 + chr(b);
b := lo(_ebx);
s := s + chr(b);
b := lo(_ecx);
s1 := s1 + chr(b);
b := lo(_edx);
s2 := s2 + chr(b);
_eax := _eax shr 8;
_ebx := _ebx shr 8;
_ecx := _ecx shr 8;
_edx := _edx shr 8;
end;
s_all := s_all + s3 + s + s1 + s2;
asm
mov eax,$80000004
db $0F
db $A2
mov _eax,eax
mov _ebx,ebx
mov _ecx,ecx
mov _edx,edx
end;
s := '';
s1 := '';
s2 := '';
s3 := '';
for i := 0 to 3 do
begin
b := lo(_eax);
s3 := s3 + chr(b);
b := lo(_ebx);
s := s + chr(b);
b := lo(_ecx);
s1 := s1 + chr(b);
b := lo(_edx);
s2 := s2 + chr(b);
_eax := _eax shr 8;
_ebx := _ebx shr 8;
_ecx := _ecx shr 8;
_edx := _edx shr 8;
end;
if s2[Length(s2)] = #0 then setlength(s2, Length(s2) - 1);
result:= s_all + s3 + s + s1 + s2;
end
else
result:= '';

end;

用这段代码就不会出现错误了!笔记本也可以!
为什么都是用汇编语言来获取呢?因为汇编获取的是动态频率,也就是说,如果你的cpu超频,那么获得的就是超频后的频率,他是根据cpu执行指令的时间来计算的,!用汇编执行指令得到的误差小,接近于cpu的执行时间!
如果想获取原始频率,这个intel和amd等公司没有公布!只有用他们的软件才能检测,因为出厂的时候,他们把这个频率写在了cpu的内部!这个是不会改变的!一旦公布这个地址,那么将来某些组织破解了,直接修改后果也就可想而知了!而且每个系列的地址都不一样
 
很谢谢lovezyp的回答,
不过你的这东东是用CPUID指令把CPU中的特征字串取出来啊,这个我早就知道了,但是这个频率更不准确了,别人超了频或降了频的机器你这东东没法用了,还有,不是每个CPU的特征字串里都含有频率的,比如老一点的INTEL和AMD的CPU就这样。
 
weiliu老兄:
你好!
你帮助我解决了不少问题,从配置机器到硬件驱动以及安装上的问题,还有刻录机的问题等等,所有这些,在我看来都是非常非常重要的,在此我表示深深的谢意!同时,我想你是否能把你的邮箱地址告诉我,以便我有问题的时候,能够及时与你勾通,谢谢!
再次表示深深的谢意!
 
后退
顶部