抓住飘忽不定的CPUID

  
最近在编写注册模块时,其中机器码的生成使用到了CPUID,而程序运行后,却发现,注册模块的校验并不是每次都有效。多次独立运行,机器码竟然是随机变化的!而当我使用IDE调试环境时,却一切正常。
经过多次观察,发现机器码在两个值之间随机取得(即非此即彼)。而在机器码生成算法中,我并没有使用到随机函数,那么问题的出现只能在使用到的两个硬件数据上。
到这里,问题应该是比较明了了,因为我想起了所用的工作站是双核的(提起双核就让我想到真假双核,呵呵),我试着在程序启动之后在“任务管理器”中手动指定单CPU运行,之后发现,随机产生机器码的问题没有了。
因此可以断定:双核CPU不同核的ID是不一样的(这也从另一个方面证明了我这块P-D 2.8是真双核咯?呵呵),而程序运行后被分配到哪个核执行是随机的,从而造成了机器码(确切的说是CPUID)不相同的问题。同时,在IDE环境调试时一切正常的原因也清楚了:IDE调试环境启动后占用一个CPU核心,而另一个核心去启动要调试的程序,只要IDE调试环境所在CPU核心不变,那该程序所在的核心也不变(此断言没有经过验证,只是我根据现象推断的,也许这个分配是由CPU运行优先级机制控制的)
那么怎么消除这种不确定性呢?一般有两种方法:
1、             指定你的程序占用第一次启动时选中的那个核心。此方法涉及到更多的CPU信息操作,相对复杂。
2、             不完全读取CPUID。由于只是使用CPUID来生成一些硬件特征码,因此,并不需要读取全部的CPUID信息,那么可以屏蔽掉不同核心标识的标志位,比如,我的代码中,屏蔽了ID2来达到此目的。
以下是从网上D下的CPUID读取功能代码,仅供参考:
interface
uses StrUtils,
     Windows,
     sysUtils;

type
    
    SCPUID    
=  array[ 1 .. 4 ] of Longint;
    SVendor    
=  array [ 0 .. 11 ] of  char ;

  TCPUInfo 
=   class (TObject)
  
private
    FID1: 
string ;
    FID2: 
string ;
    FID3: 
string ;
    FID4: 
string ;
    FAvailable: Boolean;
    FVendor: SVendor;
  
protected

  
public
    constructor create;
  published 
    property ID1: 
string  read FID1;
    property ID2: 
string  read FID2;
    property ID3: 
string  read FID3;
    property ID4: 
string  read FID4;
    property Available: Boolean read FAvailable;
  end;
const
    ID_BIT    
=     $ 200000 ;             //  EFLAGS ID bit


implementation
function IsCPUID_Available : Boolean; register;
asm
    PUSHFD                            {direct access to flags no possible, only via stack}
  POP     EAX                    {flags to EAX}
  MOV     EDX,EAX            {save current flags}
  XOR     EAX,ID_BIT    {not ID bit}
  PUSH    EAX                    {onto stack}
  POPFD                                {from stack to flags, with not ID bit}
  PUSHFD                            {back to stack}
  POP     EAX                    {
get  back to EAX}
  XOR     EAX,EDX            {check 
if  ID bit affected}
  JZ      @exit                {no, CPUID not availavle}
  MOV     AL,True            {Result
= True}
@exit:
end;

function GetCPUID : SCPUID; assembler; register;
asm
  PUSH    EBX         {Save affected register}
  PUSH    EDI
  MOV     EDI,EAX     {@Result}
  MOV     EAX,
1
  DW      $A20F       {CPUID Command}
  STOSD                      {CPUID[
1 ]}
  MOV     EAX,EBX
  STOSD               {CPUID[
2 ]}
  MOV     EAX,ECX
  STOSD               {CPUID[
3 ]}
  MOV     EAX,EDX
  STOSD               {CPUID[
4 ]}
  POP     EDI                    {Restore registers}
  POP     EBX
end;

function GetCPUVendor : SVendor; assembler; register;
asm
  PUSH    EBX                    {Save affected register}
  PUSH    EDI
  MOV     EDI,EAX            {@Result (TVendor)}
  MOV     EAX,
0
  DW      $A20F                {CPUID Command}
  MOV     EAX,EBX
  XCHG        EBX,ECX     {save ECX result}
  MOV            ECX,
4
@
1 :
  STOSB
  SHR     EAX,
8
  LOOP    @
1
  MOV     EAX,EDX
  MOV            ECX,
4
@
2 :
  STOSB
  SHR     EAX,
8
  LOOP    @
2
  MOV     EAX,EBX
  MOV            ECX,
4
@
3 :
  STOSB
  SHR     EAX,
8
  LOOP    @
3
  POP     EDI                    {Restore registers}
  POP     EBX
end;


{ TCPUInfo }

constructor TCPUInfo.create;
var
    cpuid: Scpuid;
begin
    FAvailable :
=  IsCPUID_Available;
    
    FID1 :
=   ' 00000000 ' ;
    FID2 :
=   ' 00000000 ' ;
    FID3 :
=   ' 00000000 ' ;
    FID4 :
=   ' 00000000 ' ;

    
if  FAvailable then
    begin
        cpuid :
=  getCPUID;
        FID1 :
=  inttohex(cpuid[ 1 ],  8 );
        FID2 :
=  inttohex(cpuid[ 2 ],  8 );  // 在我的机器上,屏蔽这个字段就可以获取稳定的机器码
        FID3 : =  inttohex(cpuid[ 3 ],  8 );
        FID4 :
=  inttohex(cpuid[ 4 ],  8 );
        FVendor :
=  getCPUVendor;
    end;
end;

end.
 

你可能感兴趣的:(抓住飘忽不定的CPUID)