CPUID——检测CUP信息及程序的实现

7 篇文章 0 订阅
4 篇文章 0 订阅
CPUID是Intel Pentium以上级CPU内置的一个指令(486级及以下的CPU不支持),它用于识别某一类型的CPU,它能返回CPU的级别(family),型号(model),CPU步进(Stepping ID)及CPU字串等信息,从此命令也可以得到CPU的缓存与TLB信息.
CPUID返回数据类型是在EAX寄存器里面定义的,而指令返回的数值则在存储在EAX,EBX,ECX和EDX寄存器里面.
返回的信息分两部分:基本信息与扩展信息.在EAX输入0-3参数时,它返回的CPU的基本信息;而在EAX输入0x8000000至0x800000x时,它返回的是CPU的扩展信息(extended function information).扩展信息只包含在Pentium 4及以后的CPU上,Pentium 4以前的CPU无法取得它的扩展信息.


如下面的表:
CPU级别                         基本信息   扩展信息
486及以前的CPU           不可用    不可用
Pentium                           0x1    不可用
Pentium Pro,Pentium 2    0x2    不可用
Pentium 3                        0x3    不可用
Pentium 4                        0x2    0x80000004
Xeon(至强)                      0x2    0x80000004


假若输入高于该处理器的值时,CPUID指令返回的是该CPU的输入最高值的返回值(这一句不知道怎么说才好),
比如在在Pentium 4上输入0x4,则CPU返回值与输入0x2的返回值一样.


下面的表是输入值与返回值的关系:
输入值        返回值
-----------------------------------------------------------------
0x0            EAX  CPU基本参数的输入值
                  EBX  "Genu"
                  ECX  "Intel"
                  EDX  "inel"
------------------------------------------------------------------
0x1      EAX  CPU的级别,型号及步进
            EBX  信息很多,下面介绍
            ECX  保留
            EDX  特征信息(Feature Information)
------------------------------------------------------------------
0x2      EAX到EDX返回的都是缓存和TLB的信息
------------------------------------------------------------------
0x3      EAX  保留
            EBX  保留
           ECX  CPU序列号(0 - 31bit) (只是在Pentium 3中才有效)
           EDX  CPU序列号(32 - 63bit) (只是在Pentium 3 中才有效)
------------------------------------------------------------------


0x80000000    EAX  扩展信息输入数最大值(具有扩展信息的CPU才能返回)
                        EBX  保留
                        ECX  保留
                        EDX  保留
------------------------------------------------------------------
0x80000001    EAX  CPU特征(Signature)和扩展特征位(Extended Feature Bits)
                        EBX 到 ECX  保留
------------------------------------------------------------------
0x80000002    EAX  处理器字串(Processor Brand String)
                        EBX  处理器字串(续)
                         ECX  处理器字串(续)
                        EDX  处理器字串(续)
------------------------------------------------------------------
0x80000003    EAX  处理器字串(续)
                        EBX  处理器字串(续)
                         ECX  处理器字串(续)
                        EDX  处理器字串(续)
------------------------------------------------------------------
0x80000004    EAX  处理器字串(续)
                        EBX  处理器字串(续)
                        ECX  处理器字串(续)
                         EDX  处理器字串(续)
------------------------------------------------------------------


当输入0x1时,EBX返回值是:
第 0 -  7位: CPU字串索引 (Brand Index)
第 8 - 15位: CLFLUSH线大小(CLFLUSH line size) (返回值*8 = cache line size)
第16 - 23位: 保留
第24 - 31位: 处理器APIC物理标号 (Processor local APIC physical ID)


当输入0x1时,EDX返回的扩展信息解释如下:


位  标号    解释
0  FPU  Floating Point Unit On-Chip. CPU是否内置浮点计算单元
1  VME  Virtual 8086 Mode Enhancements. 是否支持虚拟8086模式
2  DE  Debugging Extensions. 是否支持调试功能.
3  PSE  Page Size Extension. 是否支持大于4MB的分页.
4  TSC  Time Stamp Counter. 是否支持RDTSC指令.(注:RDTSC指令可以计算出CPU的频率)
5  MSR  Module Specific Registers RDMSR and WRMSR Instructions. 是否支持RDMSR与WRMSR (*注1)
6  PAE  Physical Address Extension. 是否支持大于32bit的物理地址.
7  MCE  Machine Check Exception. (*注2)
8  CX8  CMPXCHG8B Instruction. 是否支持8bytes(64bit)数的比较与交换指令.
9  APIC  APIC On-Chip.是否支持APIC(Advanced Programmable Interrupt Controller)
10  保留
11  SEP  SYSENTER and SYSEXIT Instructions.是否支持SYSENTER与SYSEXIT指令.(*注3)
12  MTRR  Memory Type Range Registers. 是否支持MTTR(*注4)
13  PGE  PTE Global Bit. 是否支持全局页面目录入口标志位 (global bit in page directory entries)
14  MCA  Machine Check Architecture. 是否支持MCA,MCA是Pentium4,Xeon,P6级处理器的一个错误报告机制
15  CMOV  Conditional Move Instructions. CMOV指令是否可用.(请问谁可以解释一下CMOV是什么命令?)
16  PAT  Page Attribute Table. 是否支持PAT,PAT允许操作系统指定4K大小的线性内存空间
17  PSE-36  32-bit Page Size Extension. 是否支持4GB的扩展内存
18  PSN  Processor Serial Number. 是否支持处理器序列号.(P3有效)
19  CLFSH  CLFLUSH Instruction.是否支持CLFLUSH.(*注5)
20  保留
21  DS  Debug Store. 是否支持把调试信息写入缓存,
22  ACPI  ACPI Processor Performance Modulation Registers. 处理器使用特别的寄存器以允许软件控制处理器的运行周期.
23   MMX  Inter MMX Technology.是否支持MMX
24  FXSR  FXSAVE and FXRSTOR Instructions. FXSAVE与FXRSTOR指令是否可用(*注6)
25  SSE  SSE.是否支持SSE.
26  SSE2  是否支持SSE2.
27  SS  Self Snoop. 处理器是否支持总线监视,以防止储存器冲突.
28  保留
29  TM  Thermal Monitor.CPU是否支持温度控制.
30 & 31  保留
--------------------------------------------------------------


按照这个,就可以自己写一个CPU检测程序了;
#include <stdio.h>


void main()
{
  unsigned long DBaseIndex, DFeInfo, DFeInfo2, DCPUBaseInfo;
  unsigned long DFeIndex, DCPUExInfo, i;
  unsigned long DOther[4], DTLB[4], DProceSN[2];
  char cCom[13];
  char cProStr[49];
  unsigned int j;


  _asm
  {
    xor eax, eax
    cpuid
    mov DBaseIndex      ,eax
    mov dword ptr cCom    ,ebx
    mov dword ptr cCom+4  ,ecx //AMD CPU要把ecx改为edx
    mov dword ptr cCom+8  ,edx //AMD CPU要把edx改为ecx
    
    mov eax, 1
    cpuid
    mov DCPUBaseInfo, eax
    mov DFeInfo, ebx 
    mov DFeInfo2, edx


    mov eax, 0x80000000
    cpuid
    mov DFeIndex, eax


    mov eax, 0x80000001
    cpuid
    mov DCPUExInfo, eax


    mov eax, 0x80000002
    cpuid
    mov dword ptr cProStr    , eax
    mov dword ptr cProStr + 4  , ebx
    mov dword ptr cProStr + 8  , ecx
    mov dword ptr cProStr + 12  ,edx


    mov eax, 0x80000003
    cpuid
    mov dword ptr cProStr + 16  , eax
    mov dword ptr cProStr + 20  , ebx
    mov dword ptr cProStr + 24  , ecx
    mov dword ptr cProStr + 28  , edx


    mov eax, 0x80000004
    cpuid
    mov dword ptr cProStr + 32  , eax
    mov dword ptr cProStr + 36  , ebx
    mov dword ptr cProStr + 40  , ecx
    mov dword ptr cProStr + 44  , edx
  }


  if( DBaseIndex >= 2 )
  {
    _asm
    {
      mov eax, 2
      cpuid
      mov DTLB[0], eax
      mov DTLB[2], ebx
      mov DTLB[3], ecx
      mov DTLB[4], edx
    }
  }
  if(DBaseIndex == 3)
  {
    _asm
    {
      mov eax, 3
      cpuid
      mov DProceSN[0], ecx
      mov DProceSN[1], edx
    }
  }


  cCom[12] = '\0'; //加一个结尾符
  printf( "CPU厂商:  %s\n", cCom );
  printf( "CPU字串:  %s\n", cProStr );
  printf( "CPU基本参数: Family:%X  Model:%X  Stepping ID:%X\n", (DCPUBaseInfo & 0x0F00) >> 8,
      (DCPUBaseInfo & 0xF0) >> 4, DCPUBaseInfo & 0xF );
  printf( "CPU扩展参数: Family:%X  Model:%X  Stepping ID:%X\n", (DCPUExInfo & 0x0F00) >> 8,
      (DCPUExInfo & 0xF0) >> 4, DCPUExInfo & 0xF );


  printf( "CPU字串索引: 0x%X\n", DFeInfo & 0xFF );
  printf( "CLFLUSH线大小: 0x%X\n", ( DFeInfo & 0xFF00 ) >> 8 );
  printf ( "处理器APIC物理标号:0x%X\n", ( DFeInfo & 0xF000 ) >> 24 );
  if( DBaseIndex >= 2)
  {
    printf( "CPU Cache & TLB Information: " );
    for(j = 0; j < 4; j++)
    {
      if( !(DTLB[j] & 0xFF) ) printf( "%.2X ", DTLB[j] & 0xFF );
      if( !((DTLB[j] & 0xFF) >> 8) ) printf( "%.2X ", (DTLB[j] & 0xFF00) >> 8 );
      if( !((DTLB[j] & 0xFF0000) >> 16) ) printf( "%.2X ",( DTLB[j] & 0xFF0000) >> 16);
      if( !((DTLB[j] & 0xFF000000) >> 24) ) printf( "%.2X ",( DTLB[j] & 0xFF000000) >> 24);
    }
    printf("\n");
  }


  if( DBaseIndex == 3 )
  {
    printf( "CPU序列号是:%X%X\n", DProceSN[0], DProceSN[1] );
  }
    printf( "FPU:  %d\t\t", DFeInfo2 & 0x00000001 ); //下面是调用某BLOG上面的代码,懒得写了 ^^
    printf( "VME:  %d\t\t", (DFeInfo2 & 0x00000002 ) >> 1 );
    printf( "DE:  %d\n", (DFeInfo2 & 0x00000004 ) >> 2 );
    printf( "PSE:  %d\t\t", (DFeInfo2 & 0x00000008 ) >> 3 );
    printf( "TSC:  %d\t\t", (DFeInfo2 & 0x00000010 ) >> 4 );
    printf( "MSR:  %d\n", (DFeInfo2 & 0x00000020 ) >> 5 );
    printf( "PAE:  %d\t\t", (DFeInfo2 & 0x00000040 ) >> 6 );
    printf( "MCE:  %d\t\t", (DFeInfo2 & 0x00000080 ) >> 7 );
    printf( "CX8:  %d\n", (DFeInfo2 & 0x00000100 ) >> 8 );
    printf( "APIC:  %d\t", (DFeInfo2 & 0x00000200 ) >> 9 );
    printf( "SEP:  %d\t\t", (DFeInfo2 & 0x00000800 ) >> 11 );
    printf( "MTRR:  %d\n", (DFeInfo2 & 0x00001000 ) >> 12 );
    printf( "PGE:  %d\t\t", (DFeInfo2 & 0x00002000 ) >> 13 );
    printf( "MCA:  %d\t\t", (DFeInfo2 & 0x00004000 ) >> 14 );
    printf( "CMOV:  %d\n", (DFeInfo2 & 0x00008000 ) >> 15 );
    printf( "PAT:  %d\t\t", (DFeInfo2 & 0x00010000 ) >> 16 );
    printf( "PSE-36:  %d\t", (DFeInfo2 & 0x00020000 ) >> 17 );
    printf( "PSN:  %d\n", (DFeInfo2 & 0x00040000 ) >> 18 );
    printf( "CLFSN:  %d\t", (DFeInfo2 & 0x00080000 ) >> 19 );
    printf( "DS:  %d\t\t", (DFeInfo2 & 0x00200000 ) >> 21 );
    printf( "ACPI:  %d\n", (DFeInfo2 & 0x00400000 ) >> 22 );
    printf( "MMX:  %d\t\t", (DFeInfo2 & 0x00800000 ) >> 23 );
    printf( "FXSR:  %d\t", (DFeInfo2 & 0x01000000 ) >> 24 );
    printf( "SSE:  %d\n", (DFeInfo2 & 0x02000000 ) >> 25 );
    printf( "SSE2:  %d\t", (DFeInfo2 & 0x04000000 ) >> 26 );
    printf( "SS:  %d\t\t", (DFeInfo2 & 0x08000000 ) >> 27 );
    printf( "TM:  %d\n", (DFeInfo2 & 0x20000000 ) >> 29 );


  printf("\n其它信息:\n");
  printf("----------------------------------------\n");
  printf("In \t\tEAX \t\tEBX \t\tECX \t\tEDX");
  for( i = 0x80000004; i <= DFeIndex; ++i )
  {
    DOther[0] = DOther[1] = DOther[2] = DOther[3] = 0;
    _asm
    {
      mov eax, i
      cpuid
      mov DOther[0], eax
      mov DOther[1], ebx
      mov DOther[2], ecx
      mov DOther[3], edx
    }
    printf( "\n0x%.8X\t0x%.8X\t0x%.8X\t0x%.8X\t0x%.8X", i, DOther[0], DOther[1], DOther[2], DOther[3] );
  }
  printf( "\n" );
  system( "pause" );
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值