匯編實現獲取CPU信息


這是文章最后一次更新,加入了TLB與Cache信息等資料
前言:論壇上面有人不明白CPUID指令的用法,於是就萌生寫這篇文章的想法,
若有錯誤話請大俠指出,謝謝了 ^^
論壇的式樣貌似有問題,若式樣問題導致閱讀問題的話,可以在文章尾下載txt文檔閱讀.

論壇上面有人不明白CPUID指令的用法,於是就萌生寫這篇文章的想法,
若有錯誤話請大俠指出,謝謝了 ^^
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  保留
--------------------------------------------------------------
注1: RDMSR: Load MSR specified by ECX into EDX:EAX
     WRMSR: Write the value in EDX:EAX to MSR specified by ECX
注2:
原文是Exception 18 is defined for Machine Checks,including CR4.MCE for controlling the feature. This feature does not define themodel-specific implementations of machine-check error logging, reporting, andprocessor shutdowns. Machine Check exception handlers may have to depend onprocessor version to do model specific processing of the exception, or test for thepresence of the Machine Check feature.

 

注3: SYSENTER: Fast call to privilege level 0 system procedures
     SYSEXIT:  Fast return to privilege level 3 user code.

注4: 
原文是The MTRRcap MSR contains feature bits that describe what memory types are supported, how manyvariable MTRRs are supported, and whether fixed MTRRs are supported.

注5: CLFLUSH: Flushes cache line containing m8.

注6: FXSAVE: Save the x87 FPU, MMX, XMM, and MXCSR register
     FXSTOR: Restore the x87 FPU, MMX, XMM, and MXCSR register


按照這個,就可以自己寫一個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" );
}

TLB與Cache信息詳解:
0x00  Null descriptor
0x01  Instruction TLB: 4K-Byte Pages, 4-way set associative, 32 entries
0x02  Instruction TLB: 4M-Byte Pages, 4-way set associative, 2 entries
0x03  Data TLB: 4K-Byte Pages, 4-way set associative, 64 entries
0x04  Data TLB: 4M-Byte Pages, 4-way set associative, 8 entries
0x06  1st-level instruction cache: 8K Bytes, 4-way set associative, 32 byte line size
0x08  1st-level instruction cache: 16K Bytes, 4-way set associative, 32 byte line size
0x0A  1st-level data cache: 8K Bytes, 2-way set associative, 32 byte line size
0x0C  1st-level data cache: 16K Bytes, 4-way set associative, 32 byte line size
0x22  3rd-level cache: 512K Bytes, 4-way set associative, 64 byte line size
0x23  3rd-level cache: 1M Bytes, 8-way set associative, 64 byte line size
0x25  3rd-level cache: 2M Bytes, 8-way set associative, 64 byte line size
0x29  3rd-level cache: 4M Bytes, 8-way set associative, 64 byte line size
0x40  No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache
0x41  2nd-level cache: 128K Bytes, 4-way set associative, 32 byte line size
0x42  2nd-level cache: 256K Bytes, 4-way set associative, 32 byte line size
0x43  2nd-level cache: 512K Bytes, 4-way set associative, 32 byte line size
0x44  2nd-level cache: 1M Byte, 4-way set associative, 32 byte line size
0x45  2nd-level cache: 2M Byte, 4-way set associative, 32 byte line size
0x50  Instruction TLB: 4-KByte and 2-MByte or 4-MByte pages, 64 entries
0x51  Instruction TLB: 4-KByte and 2-MByte or 4-MByte pages, 128 entries
0x52  Instruction TLB: 4-KByte and 2-MByte or 4-MByte pages, 256 entries
0x5B  Data TLB: 4-KByte and 4-MByte pages, 64 entries
0x5C  Data TLB: 4-KByte and 4-MByte pages,128 entries
0x5D  Data TLB: 4-KByte and 4-MByte pages,256 entries
0x66  1st-level data cache: 8KB, 4-way set associative, 64 byte line size
0x67  1st-level data cache: 16KB, 4-way set associative, 64 byte line size
0x68  1st-level data cache: 32KB, 4-way set associative, 64 byte line size
0x70  Trace cache: 12K-μop, 8-way set associative
0x71  Trace cache: 16K-μop, 8-way set associative
0x72  Trace cache: 32K-μop, 8-way set associative
0x79  2nd-level cache: 128KB, 8-way set associative, sectored, 64 byte line size
0x7A  2nd-level cache: 256KB, 8-way set associative, sectored, 64 byte line size
0x7B  2nd-level cache: 512KB, 8-way set associative, sectored, 64 byte line size
0x7C  2nd-level cache: 1MB, 8-way set associative, sectored, 64 byte line size
0x82  2nd-level cache: 256K Bytes, 8-way set associative, 32 byte line size
0x84  2nd-level cache: 1M Byte, 8-way set associative, 32 byte line size
0x85  2nd-level cache: 2M Byte, 8-way set associative, 32 byte line size

舉一個例子,一個CPU執行
mov eax, 2
cpuid
后,
返回值如下:
EAX 0x665B5001
EBX 0x0
ECX 0x0
EDX 0x007A7000
就代表了這個CPU的Cache信息是:
1. 0x66:1st-level data cache: 8KB, 4-way set associative, 64 byte line size
2. 0x5B:Data TLB: 4-KByte and 4-MByte pages, 64 entries
3. 0x50:Instruction TLB: 4-KByte and 2-MByte or 4-MByte pages, 64 entries
4. 0x01:Instruction TLB: 4K-Byte Pages, 4-way set associative, 32 entries
5. 0x7A:2nd-level cache: 256KB, 8-way set associative, sectored, 64 byte line size
6. 0x70:Trace cache: 12K-μop, 8-way set associative

CPU字串索引 (Brand Index)詳解:
0x0: CPU不支持Brand Index
0x1: Celeron CPU
0x2: Pentium 3
0x3: Pentium 3 Xeon
0x4-0x7: 未用
0x8: Pentium 4

可惜我是用AMD CPU的,有好些功能都不能親自試驗
參考資料:IA-32 Intel Architecture Software Developer’s Manual

 

http://blog.csdn.net/damenhanter/article/details/7591943


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM