1. 程式人生 > >一分鐘學會獲取CPU序列號

一分鐘學會獲取CPU序列號

        我再強調一遍,並不是所有的處理器都有序列號!Intel的文件告訴我們Pentium 4 系列的處理器不支援序列號!經過測試發現AMD的機器也沒有,奇鬱悶,看來這個Processor Serial Number實在用處不大了。然則研究了這麼久,還是貼出來吧,興許有人能用上喔。

       文件告訴我們CPU SN是一個96bit的串,可以通過調用匯編指令cpuid獲取,具體怎麼獲取看程式碼吧。才二三十行呢,呵呵。

這裡可以下到完整版的文件:

以下是Intel文件中關於Processor Serial Number的部分。

A.  Presence of Processor Serial Number
To determine if the processor serial number feature is supported, the program should set the EAX
register parameter value to “1” and then execute the CPUID instruction as follows:
MOV EAX, 01H
CPUID
After execution of the CPUID instruction, the ECX and EDX register contains the Feature Flags.
If the PSN Feature Flags, (EDX register, bit 18) equals “1”, the processor serial number feature is
supported, and enabled. If the PSN Feature Flags equals “0”, the processor serial number
feature is either not supported, or disabled.

B. Forming the 96-bit Processor Serial Number
The 96-bit processor serial number is the concatenation of three 32-bit entities.
To access the most significant 32-bits of the processor serial number the program should set the
EAX register parameter value to “1” and then execute the CPUID instruction as follows:
MOV EAX, 01H
CPUID
After execution of the CPUID instruction, the EAX register contains the Processor Signature. The
Processor Signature comprises the most significant 32-bits of the processor serial number. The
value in EAX should be saved prior to gathering the remaining 64-bits of the processor serial
number.
To access the remaining 64-bits of the processor serial number the program should set the EAX
register parameter value to “3” and then execute the CPUID instruction as follows:
MOV EAX, 03H
CPUID
After execution of the CPUID instruction, the EDX register contains the middle 32-bits, and the
ECX register contains the least significant 32-bits of the processor serial number. Software may
then concatenate the saved Processor Signature, EDX, and ECX before returning the complete 96-
bit processor serial number.
Processor serial number should be displayed as 6 groups of 4 hex nibbles (Ex. XXXX-XXXXXXXX-
XXXX-XXXX-XXXX where X represents a hex digit). Alpha hex characters should be
displayed as capital letters.

以下是獲取CPU序列號的程式碼

void ToHex(const unsigned char * szOrigin, int nSize, char * szHex)
{
 char szTemp[10];
 for(int nIndex = 0; nIndex < nSize; nIndex ++)
 {
  sprintf(szTemp, "%02X", szOrigin[nIndex]);
  if(nIndex == 0)
  {
   strcpy(szHex, szTemp);
  }
  else
  {
   strcat(szHex, szTemp);
  }
 }
}

bool DetectCPU()
{
 char szCPUDesc[13];
 memset(szCPUDesc, 0, 13);

 unsigned char szCPUSN[12];
 memset(szCPUSN, 0, 12);
 
 unsigned long ulEAX = 0U, ulEBX = 0U, ulECX = 0U, ulEDX = 0U;
 
 __try
 {
  _asm
  {
   mov eax, 1
   cpuid
   mov ulEDX, edx
   mov ulEAX, eax
  }

  //檢查是否有CPU序列號
  //注意,Intel文件中說檢測edx的第18位是從第0位開始計算的
  if(!(ulEDX & (1 << 18)))
   return false;
  //獲取序列號的後兩個WORD
  memcpy(&szCPUSN[8], &ulEAX, 4);

  _asm
  {
   mov eax, 3
   cpuid
   mov ulECX, ecx
   mov ulEDX, edx
  }
  //獲取序列號的前4個WORD
  memcpy(&szCPUSN[0], &ulECX, 4);
  memcpy(&szCPUSN[4], &ulEDX, 4);

  //獲取CPU OEM資訊
  _asm
  {
   mov eax, 0
            cpuid
            mov dword ptr szCPUDesc[0], ebx
            mov dword ptr szCPUDesc[4], edx
            mov dword ptr szCPUDesc[8], ecx
  }
 }
 __except(EXCEPTION_EXECUTE_HANDLER)
 {
  return false;
 }

 char szCPUSNHex[25];
 ToHex(szCPUSN, 12, szCPUSNHex);

char szCPUID[37];

 sprintf(szCPUID, "%s%s", szCPUDesc, szCPUSNHex);
 return true;