抓住飘忽不定的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.

 

标签:
文章分类 FK Coding
1 条评论在 “抓住飘忽不定的CPUID” 上
  1. justhxy 说道:

    谢谢 学习了

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

点赞
如果您觉得很赞,我将非常乐意接受虚拟币的捐赠,以示您对我的肯定。

比特币钱包地址:
1PqpqA8FyH3NbfCrbcRd1YxQk3LEsSEYDV
莱特币钱包地址:
LRTdmovGGVEHCKWz7JdL9aiB7VZkuNycJf
站点勋章
网站统计