Opcode | Encoding | 16-bit | 32-bit | 64-bit | Description |
---|---|---|---|---|---|
0F A2 CPUID | 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
ret
Flags 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.