Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

CPUID Enumerator and Decoder

Purpose
Sample Output
Specification
Implementation and Build Details
Enumerator Source and Build Instructions
Authenticity and Integrity

Purpose

The command line alias console program CPUPRINT.EXE for Microsoft® Windows® NT decodes and prints the information gathered from the processor’s CPUID and XGETBV instructions.

CPUPRINT.EXE enumerates the processor capabilities alias features IBRS, STIBP, IBPB, L1D_FLUSH and SSBD as well as the presence of the IA32_ARCH_CAPABILITIES and IA32_FLUSH_CMD model specific registers, introduced by AMD and Intel with firmware alias microcode updates to fix the vulnerabilities CVE-2017-5715 alias Branch Target Injection, CVE-2017-5753 alias Bounds Check Bypass, CVE-2017-5754 alias Rogue Data Cache Load, CVE-2018-3639 alias Speculative Store Bypass, CVE-2018-3640 alias Rogue System Register Read, CVE-2018-3693 alias Bounds Check Bypass Store, and CVE-2018-3615, CVE-2018-3620 plus CVE-2018-3646 alias L1 Termination Fault, better known by their nicknames Meltdown, Spectre, Spectre-NG and Foreshadow.
It also enumerates the processor capabilities alias features PCID, introduced 2010 in first generation Intel Core processors with Westmere microarchitecture, and INVPCID, introduced 2013 in fourth generation Intel Core processors with Haswell microarchitecture, both available only in long mode, i.e. to 64-bit operating systems, which are necessary to reduce the performance impact of the fix for CVE-2017-5754 alias Meltdown.

Note: when started in its own console window, for example per double-click, CPUPRINT.EXE waits for a keypress before it exits and its console window closes; it beeps once and flashes the title bar of its console window to indicate this wait state.

Sample Output

CPUPRINT.EEE shows typical output for an Intel® Atom processor.

CPUPRINT.LOG and CPUPRINT.TXT show typical outputs for Intel® Core processors.

CPUPRINT.AMD shows typical output for an AMD® Athlon processor.

CPUPRINT.ZEN shows the output for an AMD® Ryzen7 2700X processor.
CPUPRINT.ZEN2 shows the output for an AMD® Ryzen5 3600 processor.
CPUPRINT.EPYC shows the output for an AMD® EPYC 7713 processor.
CPUPRINT.EXC shows the output for an AMD® A4-9125 Radeon R3 processor with microcode update applied.

CPUPRINT.CFL shows the output for an Intel® Core i5-8400 Coffee Lake processor with microcode update applied.
CPUPRINT.NEW shows the output for an Intel® Core i7-7500U processor with microcode update applied.

CPUPRINT.ICL shows the output for an Intel® Core i5-1035G1 Ice Lake processor with microcode update applied.
CPUPRINT.HVP shows the output for the same processor running under Microsoft Hyper-V, which but exhibits significant differences to the previous output.

CPUPRINT.KVM shows the output for an Intel® Xeon® Platinum 8124M processor running under Linux’ KVM.

Specification

CPUPRINT.EXE supports multiple specifications of (real and virtualised) x86 and x64 processors from several vendors: AMD logo
AMD64 Architecture Programmer’s Manual Volume 2: System Programming
Revision 3.38, November 29, 2021
AMD64 Architecture Programmer’s Manual Volume 3: General Purpose and System Instructions
Revision 3.33, November 24, 2021
AMD64 Technology Indirect Branch Control Extension
Revision 4.10.18, April 2018
AMD64 Speculative Store Bypass Disable
Revision 5.21.18, May 2018
AMD Geode LX Processors Data Book
February 2009
Intel logo
Intel® 64 and IA-32 Architectures Software Developer’s Manuals
Revision 077, April 2022
Intel® Architecture Instruction Set Extensions and Future Features Programming Reference
Revision 044, May 2021
Intel® Software ISA Extensions
October 2017
Speculative Execution Side Channel Mitigations
Revision 2.0, May 2018
Intel® Architecture Memory Encryption Technologies Specification
Revision 1.1, December 2017
Control-flow Enforcement Technology Preview
Revision 3.0, May 2019
Intel® Itanium® Architecture Software Developer’s Manual
Revision 2.3, May 2010
Microsoft logo
Microsoft Hypervisor Top Level Functional Specification
Version 6.0b, February 2020 (which is but incomplete)
VIA logo
VIA C7-M Processor Datasheet
Revision 2.50, May 2008
VIA Eden Processor Datasheet
Revision 1.70, January 2006
VIA PadLock Programming Guide
August 2005
VIA Eden ESP Processor Datasheet
Revision 1.79, October 2004
VIA C3 Nehemiah Processor Datasheet
Revision 1.13, September 2004
VIA Antaur Processor Datasheet
July 2003

Implementation and Build Details

CPUPRINT.EXE is a pure Win32 binary executable, written from scratch in ANSI C, built with the Platform SDK for Windows Server 2003 R2 Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, but without the MSVCRT libraries, for use on Windows XP and newer versions of Windows NT as well as Windows PE.

CPUPRINT.EXE is available for the I386 alias x86 and AMD64 alias x64 processor architectures of Windows NT.
Note: on the IA64 processor architecture, the CPUID instruction is supported in the emulated I386 alias x86 execution environment only!

Note: CPUPRINT.EXE is neither based on other (abandoned or outdated) tools like cpuid, cpuid, cpuid or CPUID explorer part 1 and CPUID explorer part 2 nor related to any of them!

Enumerator Source and Build Instructions

Optionally perform the following 3 simple steps to build the console application RAWCPUID.COM from the source presented below that demonstrates the enumerator, but not the decoder, and execute it.
  1. Create the text file RAWCPUID.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2022, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    // * The software is provided "as is" without any warranty, neither express
    //   nor implied.
    // * In no event will the author be held liable for any damage(s) arising
    //   from the use of the software.
    // * Redistribution of the software is allowed only in unmodified form.
    // * Permission is granted to use the software solely for personal private
    //   and non-commercial purposes.
    // * An individuals use of the software in his or her capacity or function
    //   as an agent, (independent) contractor, employee, member or officer of
    //   a business, corporation or organization (commercial or non-commercial)
    //   does not qualify as personal private and non-commercial purpose.
    // * Without written approval from the author the software must not be used
    //   for a business, for commercial, corporate, governmental, military or
    //   organizational purposes of any kind, or in a commercial, corporate,
    //   governmental, military or organizational environment of any kind.
    
    #define STRICT
    #undef UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(safebuffers)
    BOOL	PrintFormat(HANDLE hOutput, LPCSTR lpFormat, ...)
    {
    	CHAR	szBuffer[1025];
    	DWORD	dwBuffer;
    	DWORD	dwOutput;
    
    	va_list	vaInserts;
    	va_start(vaInserts, lpFormat);
    
    	dwBuffer = wvsprintf(szBuffer, lpFormat, vaInserts);
    
    	va_end(vaInserts);
    
    	if (dwBuffer == 0)
    		return FALSE;
    #ifdef UNICODE
    	if (!WriteConsole(hOutput, szBuffer, dwBuffer, &dwOutput, NULL))
    #else
    	if (!WriteFile(hOutput, szBuffer, dwBuffer, &dwOutput, (LPOVERLAPPED) NULL))
    #endif
    		return FALSE;
    
    	return dwOutput == dwBuffer;
    }
    
    __declspec(noreturn)
    VOID	WINAPI	mainCRTStartup(VOID)
    {
    	union
    	{
    		DWORD	dw[4];	// EAX, EBX, ECX, EDX
    		WORD	w[8];
    		BYTE	b[16];
    	} CPUInfo, Default;
    #ifndef _WIN64
    	BOOL	bWoW64;
    #endif
    	DWORD	dwLeaf;
    	DWORD	dwHigh;
    	DWORD	dwSubLeaf;
    	DWORD	dwSubHigh;
    	DWORD	dwSubMask;
    	DWORD	dwError = ERROR_SUCCESS;
    	HANDLE	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	if (hOutput == INVALID_HANDLE_VALUE)
    		dwError = GetLastError();
    	else
    	{
    #ifndef _WIN64
    		if (!IsWow64Process(GetCurrentProcess(), &bWoW64))
    			PrintFormat(hOutput,
    		                    "IsWow64Process() returned error %lu\n",
    			            dwError = GetLastError());
    		else
    			if (bWoW64)
    				PrintFormat(hOutput,
    			                    "CAVEAT: some flags differ in 32-bit mode from native 64-bit mode!\n");
    #endif
    		if (SetThreadIdealProcessor(GetCurrentThread(), 0) == -1)
    			PrintFormat(hOutput,
    		                    "SetThreadIdealProcessor() returned error %lu\n",
    			            dwError = GetLastError());
    
    		PrintFormat(hOutput,
    	                    "Leaf,       SubLeaf:    EAX        EBX        ECX        EDX\n");
    
    		__cpuid(CPUInfo.dw, dwLeaf = 0x00000000);
    
    		for (dwHigh = CPUInfo.dw[0]; dwLeaf <= dwHigh; __cpuid(CPUInfo.dw, ++dwLeaf))
    		{
    			if ((CPUInfo.dw[0] == 0)
    			 && (CPUInfo.dw[1] == 0)
    			 && (CPUInfo.dw[2] == 0)
    			 && (CPUInfo.dw[3] == 0))
    				continue;
    
    			switch (dwLeaf)
    			{
    			case 0x00000004:	// Deterministic Cache Parameters
    
    				for (dwSubLeaf = 0; (CPUInfo.dw[0] & 0x0000001F) != 0; __cpuidex(CPUInfo.dw, 0x00000004, ++dwSubLeaf))
    					PrintFormat(hOutput,
    				                    "0x00000004, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				break;
    
    			case 0x00000007:	// Structured Extended Feature Flags Enumeration
    			case 0x00000014:	// Processor Trace Enumeration
    			case 0x00000017:	// System-On-Chip Vendor Attribute Enumeration
    			case 0x00000018:	// Deterministic Address Translation Parameters Enumeration
    			case 0x0000001D:	// TILE Information Enumeration
    			case 0x00000020:	// Processor History Reset Enumeration
    		//	case 0x00000021:	// Intel Trust Domain Extensions Enumeration (NEVER SHIPPED)
    
    				PrintFormat(hOutput,
    				            "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				for (dwSubHigh = CPUInfo.dw[0], dwSubLeaf = 1; dwSubLeaf <= dwSubHigh; dwSubLeaf++)
    				{
    					__cpuidex(CPUInfo.dw, dwLeaf, dwSubLeaf);
    
    					PrintFormat(hOutput,
    					            "0x%08X, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwLeaf, dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				break;
    
    			case 0x0000000B:	// Extended Topology Enumeration
    			case 0x0000001F:	// V2 Extended Topology Enumeration
    #if 0
    				for (dwSubLeaf = 0; CPUInfo.w[2] != 0; __cpuidex(CPUInfo.dw, dwLeaf, ++dwSubLeaf))
    #else
    				for (dwSubLeaf = 0; CPUInfo.b[9] != 0; __cpuidex(CPUInfo.dw, dwLeaf, ++dwSubLeaf))
    #endif
    					PrintFormat(hOutput,
    					            "0x%08X, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwLeaf, dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				break;
    
    			case 0x0000000D:	// Processor Extended State Enumeration
    
    				PrintFormat(hOutput,
    				            "0x0000000D, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				__cpuidex(CPUInfo.dw, 0x0000000D, 0x00000001);
    
    				if ((CPUInfo.dw[0] != 0)
    				 || (CPUInfo.dw[1] != 0)
    				 || (CPUInfo.dw[2] != 0)
    				 || (CPUInfo.dw[3] != 0))
    					PrintFormat(hOutput,
    					            "0x0000000D, 0x00000001: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				__cpuid(CPUInfo.dw, 0x0000000D);
    
    				for (dwSubMask = CPUInfo.dw[0] & 0xFFFFFFFC; _BitScanForward(&dwSubLeaf, dwSubMask); dwSubMask &= dwSubMask - 1)
    				{
    					__cpuidex(CPUInfo.dw, 0x0000000D, dwSubLeaf);
    
    					if ((CPUInfo.dw[0] == 0)
    					 && (CPUInfo.dw[1] == 0)
    					 && (CPUInfo.dw[2] == 0)
    					 && (CPUInfo.dw[3] == 0))
    						continue;
    
    					PrintFormat(hOutput,
    					            "0x0000000D, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				__cpuid(CPUInfo.dw, 0x0000000D);
    
    				for (dwSubMask = CPUInfo.dw[3]; _BitScanForward(&dwSubLeaf, dwSubMask); dwSubMask &= dwSubMask - 1)
    				{
    					dwSubLeaf += 32;
    
    					__cpuidex(CPUInfo.dw, 0x0000000D, dwSubLeaf);
    
    					if ((CPUInfo.dw[0] == 0)
    					 && (CPUInfo.dw[1] == 0)
    					 && (CPUInfo.dw[2] == 0)
    					 && (CPUInfo.dw[3] == 0))
    						continue;
    
    					PrintFormat(hOutput,
    					            "0x0000000D, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				break;
    
    			case 0x0000000F:	// Platform Quality of Service Monitoring Enumeration
    						// Resource Director Technology Monitoring Enumeration
    
    				PrintFormat(hOutput,
    				            "0x0000000F, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				for (dwSubMask = CPUInfo.dw[3] & 0xFFFFFFFE; _BitScanForward(&dwSubLeaf, dwSubMask); dwSubMask &= dwSubMask - 1)
    				{
    					__cpuidex(CPUInfo.dw, 0x0000000F, dwSubLeaf);
    
    					PrintFormat(hOutput,
    					            "0x0000000F, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				break;
    
    			case 0x00000010:	// Platform Quality of Service Enforcement Enumeration
    						// Resource Director Technology Allocation Enumeration
    
    				PrintFormat(hOutput,
    				            "0x00000010, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				for (dwSubMask = CPUInfo.dw[1] & 0xFFFFFFFE; _BitScanForward(&dwSubLeaf, dwSubMask); dwSubMask &= dwSubMask - 1)
    				{
    					__cpuidex(CPUInfo.dw, 0x00000010, dwSubLeaf);
    
    					PrintFormat(hOutput,
    					            "0x00000010, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				break;
    
    			case 0x00000012:	// Software Guard Extensions Enumeration
    
    				PrintFormat(hOutput,
    				            "0x00000012, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				for (dwSubLeaf = 1; dwSubLeaf < 33; dwSubLeaf++)
    				{
    					__cpuidex(CPUInfo.dw, 0x00000012, dwSubLeaf);
    
    					if ((CPUInfo.dw[0] == 0)
    					 && (CPUInfo.dw[1] == 0)
    					 && (CPUInfo.dw[2] == 0)
    					 && (CPUInfo.dw[3] == 0))
    						continue;
    
    					PrintFormat(hOutput,
    					            "0x00000012, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    
    				break;
    
    			case 0x0000001B:	// PCONFIG Information Enumeration
    
    				for (dwSubLeaf = 0; (CPUInfo.dw[0] & 0xFFF) != 0; __cpuidex(CPUInfo.dw, 0x0000001B, ++dwSubLeaf))
    					PrintFormat(hOutput,
    					            "0x0000001B, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				break;
    #if 0
    			case 0x00000000:	// Maximum Basic Leaf and Vendor Identification
    			case 0x00000001:	// Basic Processor Version and Features
    			case 0x00000002:	// Cache and Translation Lookaside Buffer Information
    			case 0x00000003:	// Processor Serial Number
    			case 0x00000005:	// MONITOR/MWAIT Information
    			case 0x00000006:	// Thermal and Power Management
    			case 0x00000008:	// RESERVED
    			case 0x00000009:	// Direct Cache Access Information
    			case 0x0000000A:	// Architectural Performance Monitoring
    			case 0x0000000C:	// RESERVED
    			case 0x0000000E:	// RESERVED
    			case 0x00000011:	// UNUSED
    			case 0x00000013:	// UNUSED
    			case 0x00000015:	// Time Stamp Counter and Nominal Core Crystal Clock Information
    			case 0x00000016:	// Processor Frequency Information Enumeration
    			case 0x00000019:	// Key Locker Enumeration
    			case 0x0000001A:	// Hybrid Enumeration
    			case 0x0000001C:	// Architectural Last Branch Record Capabilities Enumeration
    			case 0x0000001E:	// TMUL Information Enumeration
    			case 0x00000021:	// INVALID
    #endif
    			default:
    
    				PrintFormat(hOutput,
    				            "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    				break;
    
    			}
    		}
    
    		__cpuid(Default.dw, dwHigh);
    #ifdef XEON_PHI
    		__cpuid(CPUInfo.dw, dwLeaf = 0x20000000);
    
    		if ((CPUInfo.dw[0] != Default.dw[0])
    		 || (CPUInfo.dw[1] != Default.dw[1])
    		 || (CPUInfo.dw[2] != Default.dw[2])
    		 || (CPUInfo.dw[3] != Default.dw[3]))
    			for (dwHigh = CPUInfo.dw[0]; dwLeaf <= dwHigh; __cpuid(CPUInfo.dw, ++dwLeaf))
    			{
    				if ((CPUInfo.dw[0] == 0)
    				 && (CPUInfo.dw[1] == 0)
    				 && (CPUInfo.dw[2] == 0)
    				 && (CPUInfo.dw[3] == 0))
    					continue;
    
    				PrintFormat(hOutput,
    				            "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    			}
    #endif // XEON_PHI
    		__cpuid(CPUInfo.dw, dwLeaf = 0x40000000);
    
    		if ((CPUInfo.dw[0] != Default.dw[0])
    		 || (CPUInfo.dw[1] != Default.dw[1])
    		 || (CPUInfo.dw[2] != Default.dw[2])
    		 || (CPUInfo.dw[3] != Default.dw[3]))
    			for (dwHigh = CPUInfo.dw[0]; dwLeaf <= dwHigh; __cpuid(CPUInfo.dw, ++dwLeaf))
    			{
    				if ((CPUInfo.dw[0] == 0)
    				 && (CPUInfo.dw[1] == 0)
    				 && (CPUInfo.dw[2] == 0)
    				 && (CPUInfo.dw[3] == 0))
    					continue;
    
    				PrintFormat(hOutput,
    				            "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    			}
    
    		__cpuid(CPUInfo.dw, dwLeaf = 0x80000000);
    
    		if ((CPUInfo.dw[0] != Default.dw[0])
    		 || (CPUInfo.dw[1] != Default.dw[1])
    		 || (CPUInfo.dw[2] != Default.dw[2])
    		 || (CPUInfo.dw[3] != Default.dw[3]))
    			for (dwHigh = CPUInfo.dw[0]; dwLeaf <= dwHigh; __cpuid(CPUInfo.dw, ++dwLeaf))
    			{
    				if ((CPUInfo.dw[0] == 0)
    				 && (CPUInfo.dw[1] == 0)
    				 && (CPUInfo.dw[2] == 0)
    				 && (CPUInfo.dw[3] == 0))
    					continue;
    
    				switch (dwLeaf)
    				{
    				case 0x8000001D:	// Cache Topology Information
    
    					for (dwSubLeaf = 0; (CPUInfo.dw[0] & 0x0000001F) != 0; __cpuidex(CPUInfo.dw, 0x8000001D, ++dwSubLeaf))
    						PrintFormat(hOutput,
    						            "0x8000001D, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    						            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    					break;
    
    				case 0x80000020:	// Bandwidth Enforcement Information
    
    					PrintFormat(hOutput,
    					            "0x80000020, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    
    					for (dwSubMask = CPUInfo.dw[1] & 0xFFFFFFFE; _BitScanForward(&dwSubLeaf, dwSubMask); dwSubMask &= dwSubMask - 1)
    					{
    						__cpuidex(CPUInfo.dw, 0x80000020, dwSubLeaf);
    
    						if ((CPUInfo.dw[0] == 0)
    						 && (CPUInfo.dw[1] == 0)
    						 && (CPUInfo.dw[2] == 0)
    						 && (CPUInfo.dw[3] == 0))
    							continue;
    
    						PrintFormat(hOutput,
    						            "0x80000020, 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    						            dwSubLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    					}
    
    					break;
    #if 0
    				case 0x80000000:	// Maximum Extended Leaf and Vendor Identification
    				case 0x80000001:	// Extended Processor Information and Features
    				case 0x80000002:	// Processor Brand String, Part 1
    				case 0x80000003:	// Processor Brand String, Part 2
    				case 0x80000004:	// Processor Brand String, Part 3
    				case 0x80000005:	// L1 Cache and Translation Lookaside Buffer Configuration
    				case 0x80000006:	// L2 Cache and Translation Lookaside Buffer Configuration
    				case 0x80000007:	// Thermal and Power Management Capabilities
    				case 0x80000008:	// Virtual and Physical Address Sizes
    				case 0x8000000A:	// Secure Virtual Machine Information
    				case 0x80000019:	// Translation Lookaside Buffer Configuration
    				case 0x8000001A:	// Performance Optimization Identifiers
    				case 0x8000001B:	// Instruction Based Sampling Identifiers
    				case 0x8000001C:	// Light-Weight Profiling Capabilities
    				case 0x8000001E:	// Extended Advanced Programmable Interrupt Controller Information
    				case 0x8000001F:	// Secure Memory Encryption and Secure Encrypted Virtualization Information
    				case 0x80000021:	// Extended Feature Identification 2
    				case 0x80000022:	// Extended Performance Monitoring and Debug
    #endif
    				default:
    
    					PrintFormat(hOutput,
    					            "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    					            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    				}
    			}
    
    		__cpuid(CPUInfo.dw, dwLeaf = 0xC0000000);
    
    		if ((CPUInfo.dw[0] != Default.dw[0])
    		 || (CPUInfo.dw[1] != Default.dw[1])
    		 || (CPUInfo.dw[2] != Default.dw[2])
    		 || (CPUInfo.dw[3] != Default.dw[3]))
    			for (dwHigh = CPUInfo.dw[0]; dwLeaf <= dwHigh; __cpuid(CPUInfo.dw, ++dwLeaf))
    			{
    				if ((CPUInfo.dw[0] == 0)
    				 && (CPUInfo.dw[1] == 0)
    				 && (CPUInfo.dw[2] == 0)
    				 && (CPUInfo.dw[3] == 0))
    					continue;
    
    				PrintFormat(hOutput,
    			                    "0x%08X, 0x00000000: 0x%08X 0x%08X 0x%08X 0x%08X\n",
    				            dwLeaf, CPUInfo.dw[0], CPUInfo.dw[1], CPUInfo.dw[2], CPUInfo.dw[3]);
    			}
    	}
    
    	ExitProcess(dwError);
    }
  2. Run the following four command lines to compile the source file RAWCPUID.C created in step 1., link the compiled object file RAWCPUID.OBJ and cleanup afterwards:

    SET CL=/GA /GF /GS /Gw /Gy /O1 /Os /Oy /W4 /Zl
    SET LINK=/DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:mainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OSVERSION:5.1 /OUT:RAWCPUID.COM /RELEASE /SUBSYSTEM:CONSOLE,5.1 /SWAPRUN:CD,NET /VERSION:0.815
    CL.EXE RAWCPUID.C
    ERASE RAWCPUID.OBJ

    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Note: the command lines can be copied and pasted as block into a Command Processor window!

    Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    RAWCPUID.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
  3. Finally execute the console application RAWCPUID.COM built in step 2.:

    .\RAWCPUID.COM
    CAVEAT: some flags differ in 32-bit mode from native 64-bit mode!
    Leaf,       SubLeaf:    EAX        EBX        ECX        EDX
    0x00000000, 0x00000000: 0x0000000D 0x756E6547 0x6C65746E 0x49656E69
    0x00000001, 0x00000000: 0x0001067A 0x00020800 0x0C08E3FD 0xBFEBFBFF
    0x00000002, 0x00000000: 0x05B0B101 0x005657F0 0x00000000 0x2CB43048
    0x00000004, 0x00000000: 0x04000121 0x01C0003F 0x0000003F 0x00000001
    0x00000004, 0x00000001: 0x04000122 0x01C0003F 0x0000003F 0x00000001
    0x00000004, 0x00000002: 0x04004143 0x02C0003F 0x00000FFF 0x00000001
    0x00000005, 0x00000000: 0x00000040 0x00000040 0x00000003 0x03122220
    0x00000006, 0x00000000: 0x00000003 0x00000002 0x00000003 0x00000000
    0x00000008, 0x00000000: 0x00000400 0x00000000 0x00000000 0x00000000
    0x0000000A, 0x00000000: 0x07280202 0x00000000 0x00000000 0x00000503
    0x0000000D, 0x00000000: 0x00000003 0x00000240 0x00000240 0x00000000
    0x80000000, 0x00000000: 0x80000008 0x00000000 0x00000000 0x00000000
    0x80000001, 0x00000000: 0x00000000 0x00000000 0x00000001 0x20100000
    0x80000002, 0x00000000: 0x65746E49 0x2952286C 0x726F4320 0x4D542865
    0x80000003, 0x00000000: 0x44203229 0x43206F75 0x20205550 0x50202020
    0x80000004, 0x00000000: 0x30303738 0x20402020 0x33352E32 0x007A4847
    0x80000006, 0x00000000: 0x00000000 0x00000000 0x0C006040 0x00000000
    0x80000008, 0x00000000: 0x00003024 0x00000000 0x00000000 0x00000000

Authenticity and Integrity

CPUPRINT.EXE is digitally signed using a (self-issued) X.509 leaf certificate and time stamped.

Download and install the (self-signed) X.509 root certificate to validate and verify the digital certificate and the signature.

Contact

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2022 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>