| Opcode | Encoding | 16-bit | 32-bit | 64-bit | Description |
|---|---|---|---|---|---|
0F A2CPUID | zo | Valid | Valid | Valid | Using the value in EAX (and sometimes also ECX), get information about the processor and supported features. The results are returned in EAX, EBX, ECX, and EDX. |
Encoding
| Encoding | Operand |
|---|---|
zo | N/A |
Description
The CPUID instruction, using the value in EAX (and sometimes also ECX), returns information about the processor and supported features. The results are stored in EAX, EBX, ECX, and EDX.
This instruction was introduced in 1993 with the Pentium and SL-enhanced 80486 processors. Support for it is indicated by the ability to toggle the ID bit (bit 21) in EFLAGS. On unsupported processors, setting of that bit will be ignored by the processor while executing a POPF instruction.
The supported values of EAX may vary between processors, but the EAX=0 "leaf" will always be supported, and is used to determine the maximum supported leaf. A list of the returned values is available on a dedicated page.
This instruction is serializing.
Operation
public void CPUID()
{
// "extended" leafs are ones with the MSB set
bool extended = (EAX & 0x8000_0000) != 0;
// only Pentium 4 and newer support extended leafs
extended &= ProcessorSupportsExtendedLeafs();
if (ProcessorSupportsLeaf(EAX, ECX))
{
(EAX, EBX, ECX, EDX) = CPUIDCore(EAX, ECX);
}
else if ((extended && EAX < MAX_EXTENDED_LEAF) ||
(!extended && EAX < MAX_LEAF))
{
// less than the maximum supported leaf, but this specific leaf is unsupported
// e.g. leaf 0x11 does not exist
EAX = 0;
EBX = 0;
ECX = 0;
EDX = 0;
}
else
{
// greater than the maximum supported leaf
// return the maximum
U32 leaf = extended ? MAX_EXTENDED_LEAF : MAX_LEAF;
(EAX, EBX, ECX, EDX) = CPUIDCore(leaf, ECX);
}
}Examples
; bool IsCpuidSupported();
; Determine if the CPUID instruction is supported.
;
; Clobbers: EBX
IsCpuidSupported:
pushfd ; EAX = EFLAGS
pop eax
mov ebx, eax ; save a copy
xor eax, 0x00200000 ; toggle bit 21
push eax ; EFLAGS = EAX
popfd ; if CPUID is unsupported, the change to bit 21 is ignored
pushfd ; EAX = EFLAGS
pop eax
cmp eax, ebx ; has bit 21 changed?
jne .unsupported
mov eax, 1
ret
.unsupported:
mov eax, 0
ret; bool IsCpuFromIntel();
; Determine if the current CPU is from Intel.
;
; Clobbers: EBX, ECX, EDX
IsCpuFromIntel:
mov eax, 0 ; CPUID leaf 0
cpuid
cmp ebx, 'Genu' ; in little endian; 'uneG' in big endian
jne .notIntel
cmp ecx, 'ineI' ; ditto
jne .notIntel
cmp edx, 'ntel' ; ditto
jne .notIntel
mov eax, 1
ret
.notIntel:
mov eax, 0
ret; bool IsCpuFromAMD();
; Determine if the current CPU is from AMD.
;
; Clobbers: EBX, ECX, EDX
IsCpuFromAMD:
mov eax, 0 ; CPUID leaf 0
cpuid
cmp ebx, 'Auth' ; in little endian; 'htuA' in big endian
jne .notAMD
cmp ecx, 'enti' ; ditto
jne .notAMD
cmp edx, 'cAMD' ; ditto
jne .notAMD
mov eax, 1
ret
.notAMD:
mov eax, 0
retFlags Affected
None.Intrinsics
// Microsoft specific
void __cpuid(int cpuInfo[4], int function_id)
void __cpuindex(int cpuInfo[4], int function_id, int subfunction_id)Exceptions
Real-Address Mode
#UD- If the
LOCK- prefix is used.
Virtual-8086 Mode
#UD- If the
LOCK- prefix is used.
Protected Mode
#UD- If the
LOCK- prefix is used.
Compatibility Mode
#UD- If the
LOCK- prefix is used.
Long Mode
#UD- If the
LOCK- prefix is used.