Three Ways to Retrieve Processor Information

If you are looking for processor information, there are several ways to get them. In this article, I'll show how to use assembly, Registry information, or Platform SDK functions to retrieve information about CPU. You can also get processor information using WMI (Windows Management Instrumentation) or Active Directory. The methods I present work for systems with one processor from Intel or AMD.

CPU Models

Each processor model is identified by a series of numbers returned by CPUID (see below) function 1. The bits returned in EAX are:

Bits Description
0 - 3 Stepping
4 - 7 Model
8 - 11 Family
12 - 13 Processor Type
16 - 19 Extended Model
20 - 27 Exdented Family

If you know the family and model and the processor vendor, you can determine what processor you do have. The vendor name, a 12-byte string, is "GenuineIntel" for Intel's processors and "AuthenticAMD" for AMD's processor. Both family and model are 4-bit integers. The tables below show the family and model for AMD's and Intel's processors.

AMD

Family Model Name
4 3 486 DX2
  7 486 DX2-WB
  8 486 DX4
  9 486 DX4-WB
  14 Am5x86-WT
  15 Am5x86-WB
5 0 K5 SSA5
  1 - 3 K5
  6 - 7 K6
  8 K6-2
  9 K6-3
  13 K6-3+
6 0-1 Athlon (0.25um)
  2 Athlon (0.18um)
  3 Duron
  4 Athlon Thunderbird
  6 Athlon Palamino
  7 Duron Morgan
  8 Athlon Thoroughbred
  10 Athlon Barton
15   Extended family table must be used

Extended Family Model Name
0 4 Athlon 64
  5 Athlon 64FX Operon

INTEL

Family Model Name
4 0 486DX-25/33
  1 486DX-50
  2 486SX
  3 486DX2
  4 486SL
  5 486SX2
  7 486DX2-WB
  8 486DX4
  9 486DX4-WB
5 0 Pentium 60/66 A-step
  1 Pentium 60/66
  2 Pentium 75-200
  3 OverDrive PODP5V83
  4 Pentium MMX
  7 Mobile Pentium 75-200
  8 Mobile Pentium MMX
6 1 Pentium Pro A-Step
  2 Pentium Pro
  3 Pentium II Klamath
  5 Pentium II Deschutes
  6 Celeron Mendocino
  7 Pentium III Katmai
  8 Pentium III Coppermine
  9 Mobile Pentium III
  10 Pentium III (0.18um)
  11 Pentium III (0.13um)
7   Itanium
15   Extended family table must be used

Extended Family Model Name
0 0-1 Pentium IV (0.18um)
  2 Pentium IV (0.13um)
  3 Pentium IV (0.09um)
1   Itanium 2

To see the table with family and model numbers for other companies, see:

To learn more about AMD processor recognition, see:

Three Ways to Retrieve Processor Information

The Assembly Method

To retrieve CPU information, you must use the CPUID (Central Processing Unit Identification) instruction. You can test whether your CPU supports this instruction like this:

bool CPUID_supported()
{
   __try {
      _asm {
         xor eax, eax
         cpuid
      }
   }
   __except (EXCEPTION_EXECUTE_HANDLER) {
      return false;
   }
   return true;
}

The following steps must be taken to get processor information:

  1. Establish that the processor has support for CPUID.
  2. Execute CPUID function 0, which returns the processor vendor string and the highest standard function supported.
  3. If step 2 indicates that the highest standard function is at least 1, execute CPUID function 1, which returns the standard feature flags in the EDX register.
  4. If bit 23 of the standard feature flags is set to 1, MMX technology is supported. MMX instruction support is the basic minimum processor feature required to support other instruction extensions.
  5. Optionally, if bit 25 of the standard feature flags is set, the processor has streaming SIMD extensions (SSE) capabilities. Further qualification of SSE is done by checking for OS support. SSE support might be present in the processor, but not usable due to a lack of OS support for the additional architected registers.
  6. Execute CPUID extended function 80000000h. This function returns the highest extended function supported in EAX. If EAX=0, there is no support for extended functions.
  7. If the highest extended function supported is at least 8000_0001h, execute CPUID function 80000001h. This function returns the extended feature flags in EDX.
  8. If bit 31 of the extended feature flags is set to 1, the 3DNow! instructions are supported.
  9. If the vendor string contains "AuthenticAMD", continue on to the next step.
  10. If bit 30 of the extended feature flags is set to 1, the additions to the 3DNow! instruction set are supported.
  11. If bit 22 of the extended feature flags is set to 1, the new multimedia enhancement instructions that augment the MMX instruction set are supported.

All this is put in CPUAssembly class presented below.

The Registry Method

Windows keeps processor information in the Registry. For each processor present in the system there is a Registry key, called, 0, 1, etc. in

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor

If you have a single processor, there is only key 0. The values under this key are:

Value Description
~MHz Speed in MHz
Component Information Processor information
Configuration Data Configuration data
FeatureSet bit flags for supported features
Identifier Contains family, model, and stepping
ProcessorNameString Processors name
Update Status Update status
VendorIdentifier Vendor name

Similarly, for each floating point processor there is a key named 0, 1, etc. in

HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\FloatingPointProcessor

See the CPURegistry class below.

The Platform SDK Method

You must have Platform SDK installed on your computer to use this method.

Windows System Information section of Platform SDK provides functions to retrieve or set system information. GetSystemInfo() and IsProcessorFeaturePresent() can be used to find processor related information.

The GetSystemInfo() function returns information about the current system and uses SYSTEM_INFO structure which contains information about the current computer system. This includes the architecture and type of the processor, the number of processors in the system, the page size, and other such information. See MSDN for more.

The IsProcessorFeaturePresent() function determines whether the specified processor feature, such as MMX, SEE, or 3DNow is supported by the current computer.

Putting All Together

To show how each method can be used to retrieve processor information, I have created three classes CPUAssembly, CPURegistry, and CPUPlatformSDK. All of them are derived from an abstract class called ICPUInfo:

class ICPUInfo
{
public:
   virtual bool QueryCPUInfo() = 0;
   virtual unsigned __int64 GetSpeed() const;
   std::string FormatSpeed(unsigned __int64 speed) const;
   virtual unsigned int GetSpeedMHz()const = 0;

   virtual std::string GetCPUName() const   = 0;
   virtual std::string GetVendorName() const;
   std::string GetCPUName(std::string vendor, short int family,
                          short int model, short int family_ex,
                          short int model_ex) const;
   virtual short int GetCPUFamily() const   = 0;
   virtual short int GetCPUModel() const    = 0;
   virtual short int GetCPUStepping() const = 0;

   virtual bool IsMMXSupported() const   = 0;
   virtual bool IsSSESupported() const   = 0;
   virtual bool IsSSE2Supported() const  = 0;
   virtual bool Is3DNowSupported() const = 0;
};

QueryCPUInfo() retrieves the processor information and must be call first. If this method returns false, processor information could not be retrieved. Call the other methods only if the returned value is true.

GetSpeed() returns the speed of CPU. The assembly and Platform SDK implementations use the same method for speed measurement, and the returned value is in Hz.

unsigned __int64 ICPUInfo::GetSpeed() const
{
   unsigned __int64 start, stop;
   unsigned __int64 nCtr, nFreq, nCtrStop;

   QueryPerformanceFrequency((LARGE_INTEGER *)&nFreq);
   _asm _emit 0x0F
   _asm _emit 0x31
   _asm mov DWORD PTR start, eax
   _asm mov DWORD PTR [start+4], edx
   QueryPerformanceCounter((LARGE_INTEGER *)&nCtrStop);
   nCtrStop += nFreq;
   do
   {
      QueryPerformanceCounter((LARGE_INTEGER *)&nCtr);
   }while (nCtr < nCtrStop);

   _asm _emit 0x0F
   _asm _emit 0x31
   _asm mov DWORD PTR stop, eax
   _asm mov DWORD PTR [stop+4], edx

   return (stop-start);
}

GetSpeedMHz() returns the speed in MHz.

FormatSpeed() returns the CPU's speed in normalized format. Eg: 166MHz, 1.39GHz.

GetCPUName() returns the name of the processor.

GetVendorName() returns the name of processor vendor, which is 12 bytes long.

GetCPUFamily() returns the family number, a 4-bits value.

GetCPUModel() returns the model number, a 4-bits value.

GetCPUStepping() returns the processor revision number.

IsMMXSupported() returns true if MMX instruction set is present.

IsSSEupported() returns true if SSE (Streaming SIMD Extensions) instruction set is present.

IsSSE2Supported() returns true if SSE2 instruction set is present.

Is3DNowSupported() returns true if 3DNow! instruction set is present.

A simple example with all the three classes is presented below:

void PrintCPUInfo(ICPUInfo* info)
{
   if(!info->QueryCPUInfo())
      return;

   cout << "Name:\t\t" << info->GetCPUName() << endl;
   cout << "Speed:\t\t" << info->GetSpeedMHz() << "MHz" << endl;
   cout << "Vendor:\t\t" << info->GetVendorName() << endl;
   cout << "Family:\t\t" << info->GetCPUFamily() << endl;
   cout << "Model:\t\t" << info->GetCPUModel() << endl;
   cout << "Stepping:\t" << info->GetCPUStepping() << endl;
   cout << "Features" << endl;
   cout << "\tMMX:\t" << (info->IsMMXSupported() ? "yes" : "no")
        << endl;
   cout << "\t3DNow:\t" << (info->Is3DNowSupported() ? "yes" : "no")
        << endl;
   cout << "\tSSE:\t" << (info->IsSSESupported() ? "yes" : "no")
        << endl;
   cout << "\tSSE2:\t" << (info->IsSSE2Supported() ? "yes" : "no")
        << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
   ICPUInfo* reg = new CPURegistry;
   cout << "----- REGISTRY METHOD -------" << endl;
   PrintCPUInfo(reg);
   delete reg;

   ICPUInfo* sdk = new CPUPlatformSDK;
   cout << "----- PLATFORM SDK METHOD -------" << endl;
   PrintCPUInfo(sdk);
   delete sdk;

   CPUAssembly* assembly = new CPUAssembly;
   cout << "----- ASSEMBLY METHOD -------" << endl;
   PrintCPUInfo(assembly);
   delete assembly;

   return 0;
}

See the attached files for more details.

References

See these links for further references and related topics:



About the Author

Marius Bancila

Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for a Norwegian-based company. He is mainly focused on building desktop applications with MFC and VC#. He keeps a blog at www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++/VC++ programmers.

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • In support of their business continuity and disaster recovery plans, many midsized companies endeavor to avoid putting all their eggs in one basket. Understanding the critical role of last-mile connectivity and always available Internet access for their enterprises, savvy firms utilize redundant connections from multiple service providers. Despite the good intentions, their Internet connectivity risk may still be in a single basket. That is because internet service providers (ISPs) and competitive local …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds