最近在编写注册模块时,其中机器码的生成使用到了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 Hook是一种技术,用于拦截和修改CPU的`CPUID`指令执行,从而改变处理器返回的信息。`CPUID`指令是x86架构处理器提供的一种功能,它允许软件查询和识别处理器的特性、ID以及一些硬件配置信息。通过hook这个指令...
在编程领域,获取CPUID(CPU标识符)是一项重要的任务,尤其是在进行系统优化、硬件检测或软件兼容性检查时。CPUID是一个处理器提供的指令,它允许软件查询处理器的特性、制造商信息以及某些性能数据。在Visual C++ ...
`cpuid_hook`是一个涉及到计算机硬件交互和操作系统内核编程的技术主题,主要通过虚拟化技术中的VMX(Virtual Machine Extensions)来实现对CPUID指令的钩子(hook)。CPUID是一个在x86架构下的处理器指令,用于获取...
memset(cpuid,0,len); int cpuInfo[4] = {-1}; __cpuid(cpuInfo, 0x0); //0X0指定要在EAX中传递的要检索的信息的代码 int _data[14][4]={0}; //nIds_一般情况为13,因此定义数组长度为14,实际上cpuid取值为:_...
CPUID(CPU Identification)是计算机处理器的一个重要功能,它允许软件查询处理器的特性、标识和状态。这个功能是由Intel在1990年代初期引入的,后来被所有主流的x86架构处理器所支持,包括AMD和VIA等其他厂商的...
在IT领域,尤其是在系统编程和性能优化中,CPUID是一个重要的概念。CPUID(CPU Identifier)是处理器提供的一种指令,允许软件查询处理器的特性、标识和状态信息。它提供了访问处理器内部信息的途径,比如处理器家族...
在计算机硬件领域,CPUID(CPU Identification)是一个重要的指令,用于获取处理器的标识信息,包括制造商、型号、特征等。本文将详细介绍三种方法来获取CPUID,并通过C++类实现,同时结合VC(Visual C++)工程进行...
获取cpuid,只是这么一个功能 获取cpuid,只是这么一个功能
"CPUID.zip"这个压缩包可能包含了与CPUID相关的工具或库,特别是"CPUID_HOOK_CPUID.dll"和"CpuId DLL_hook cpuid"这两个文件,它们可能是一个动态链接库(DLL)文件,用于钩取(hook)CPUID指令,从而在CPU执行CPUID...
CPUID(CPU Identification)是x86架构处理器提供的一种硬件级指令,用于查询和识别处理器的相关信息,包括但不限于制造商、型号、步进、特性、缓存大小以及性能指标等。这个功能在系统软件、硬件诊断工具和基准测试...
在IT领域,CPUID(Central Processing Unit ID)是一种在x86架构的计算机处理器中用于获取硬件信息的指令。CPUID提供了访问处理器特征、性能监控功能以及系统配置信息的手段。在C#编程中,虽然它不是原生支持的特性...
### CPUID:Intel处理器识别与CPUID指令应用说明 #### 概述 CPUID(Central Processing Unit Identification)是一项由Intel开发的技术,它主要用于提供处理器详细信息的功能。此技术通过CPUID指令来实现,该指令...
在IT领域,Intel处理器的CPUID指令是程序员和硬件工程师们深入理解处理器特性和功能的重要工具。这份由Intel发布的文档,即"Intel® Processor Identification and the CPUID Instruction Application Note 485",...
CPUID(CPU Identifier)是x86架构处理器提供的一种指令集,用于获取CPU的相关信息,如制造商、型号、特征和性能等。在给定的"获取cpuid的源代码"中,我们可以推测这是一个C++程序,它实现了通过CPUID指令获取CPU...
标题中的"cpuid.rar"指的是一个关于CPUID功能的压缩文件,其中包含了VC++(Visual C++)的实现,以及汇编语言(ASM)的相关代码。CPUID是x86架构处理器提供的一种指令集,用于获取处理器和其他硬件的标识信息。这个...
### CPUID指令详解 在计算机科学领域,CPUID指令是一个重要的功能,主要用于识别处理器的特性、类型以及制造商信息。此指令对于系统软件如操作系统、BIOS等尤其关键,因为它们可以利用这些信息来优化硬件资源的管理...
CPUID(CPU Identification)是x86架构处理器提供的一种功能,允许软件查询CPU的特性、标识符和其他相关信息。CPUID指令在汇编语言中通过一个特殊的CPU指令执行,其主要目的是获取处理器的能力、制造商信息、时钟...
【标题】"cpuid hook(通过VMX技术,实现hook cpuid) c++.zip" 描述了一种使用C++编程语言实现CPUID指令的hook技术,该技术是通过虚拟化扩展(VMX)来实现的。CPUID是x86架构处理器上的一种指令,用于获取处理器和...
### 获取本机CPUID知识点详解 #### 一、概述 CPUID是指中央处理器(CPU)的唯一标识符,它能够帮助我们识别出特定型号的CPU。在计算机领域中,CPUID常常被用来进行硬件诊断、系统兼容性测试以及性能监控等操作。...
在IT领域,获取CPUID和使用MD5加密是两种常见的技术操作。CPUID是一种用于获取处理器标识符的指令,而MD5(Message-Digest Algorithm 5)则是一种广泛使用的哈希函数,常用于数据完整性检查和加密。接下来,我们将...