目次

ニュース

日記カテゴリ

書庫

2008年3月27日

CPUID命令を使って、CPUの情報をプログラムで探ってみましょう。

もちろん、アセンブラ命令はCPUIDを使います。ちなみにここで扱うのはIntelCPUです。

CPUIDって命令がたくさん使える上に、動作の種類が大量にあるので、ファンクション0(ベンダー文字列の取得)と、ファンクション1(CPU情報の取得)をやってみます。

CPUIDは、EAXに命令を入れて、cpuidを実行することで、eax, ebx, ecx, edxレジスタにそれぞれ情報が返ってきます。

まず、ファンクション0。

mov eax, 0

cpuid

上記の命令を実行すると、ASCII文字列で、GenuireIntelという文字が返ってきます。(ソース参照)

 

次にファンクション1です。

mov eax, 1

cpuid

この命令を実行することで、EAXにプロセッサシグネチャ、EBXにファンクションフラグ、ECXにFeatureFlag2, EDXにFeatureFlag1が返ってきます。

プロセッサシグネチャの内部構成は次の通りです。

プロセッサシグネチャ

Bit 0~3: Stepping ID

Bit 4~7: Model Number

Bit 8~11: Family Code

Bit 12~13: Processor Type

Bit 14~15: Reserved

Bit 16~19: Extended Model

Bit 20~27: Extended Family

Bit 28~31: Reserved

このうち、Model NumderとFamily Codeの組み合わせでCPUを判断することができます。

(厳密にはProcessor TypeでOverdriveがあったり、Extended Modelでさらに分岐があったりしますが)

ファンクションフラグは、通信用語の基礎知識を見ると以下の通りのようです。

Bit 31~24: APIC ID

Bit 23~16: 論理CPU数

Bit 15~8: CLFLUSH

Bit 7~0: ブランドID

Feature Flag1および2については、CPUにSSEやHTTなどの機能が存在するかかどうかをCPUのフラグで判別できます。

ここでは長くなるので、割愛さしてもらいますが・・・。

詳しくは、こちらから。http://download.intel.com/design/processor/applnots/24161832.pdf

 

ということで、ここではプロセッサシグネチャについて、実際にプログラムで確認してみます。

コンパイラーはVisual C++ 9.0 Express Editionです。

001 #include "stdafx.h"
002 #include <iostream>
003 
004 int _tmain(int argc, _TCHAR* argv[])
005 {
006     typedef unsigned int DWORD;
007 
008     struct _cpumatrix {
009         unsigned char cpu_code;
010         std::string desc;
011     } cpumatrix[] = 
012     { 
013         // CPUのマトリックステーブル。左側にFamilyCode, ModelNumberと右側にCPUの文字列を対応づけます。
014         { 0x40, "Intel486 DX processor"},
015         { 0x41, "Intel486 DX processor"},
016         { 0x43, "IntelDX2 processor"},
017         { 0x44, "Intel486 SL processor"},
018         { 0x45, "IntelSX2 processors"},
019         { 0x47, "Write-Back Enhanced IntelDX2 processors"},
020         { 0x48, "IntelDX4 processor"},
021         { 0x51, "Pentium processors(60,66)"},
022         { 0x52, "Pentium Processors(75,90,100,120,133,150,166,200)"},
023         { 0x54, "Pentium processor with MMX technology(166,200)"},
024         { 0x61, "Pentium Pro processor"},
025         { 0x63, "Pentium II processor, model03"},
026         { 0x65, "Pentium II processor, model05, PentiumII Xeon processor, Intel Celeron processor"},
027         { 0x66, "Celeron processor, model06"},
028         { 0x67, "Pentium III processor, model07, and Pentium III Xeon processor, model07"},
029         { 0x68, "Pentium III processor, model 08,Pentium III Xeon processor, model 08,and Celeron processor, model 08"},
030         { 0x69, "Intel Pentium M processor, Intel Celeron M processor model 09"},
031         { 0x6A, "Pentium III Xeon processor, model0Ah"},
032         { 0x6B, "Pentium III processor, model 0Bh"},
033         { 0x6D, "Intel Pentium M processor,90 nm process."},
034         { 0x6E, "Intel Core Duo processor, 65 nm process."},
035         { 0x6F, "Intel Core2 Duo processor, 65 nm process."},
036         { 0xF0, "Pentium 4 processor."},
037         { 0xF1, "Pentium 4 Processor 0.18um process."},
038         { 0xF2, "Pentium 4 Processor 0.13um process."},
039         { 0xF3, "Pentium 4 Processor, Celeron D Processor"},
040         { 0xF4, "Pentium 4 Processor, Pentium D Processor 90nm process"},
041         { 0xF6, "Pentium 4 Processor, Pentium D Processor 65nm process"},
042         { 0x00, "unknown processor"}
043     };
044 
045 
046     // ベンダーIDのチェック
047     char vender_sig[13];
048     __asm {
049         mov eax, 0;                                /* EAXに0を入れる */
050         cpuid;                                    /* CPUID実行 */
051         mov dword ptr [vender_sig + 0], ebx;    /* 最初の4文字 */
052         mov dword ptr [vender_sig + 4], edx;    /* 次の4文字 */
053         mov dword ptr [vender_sig + 8], ecx;    /* 最後の4文字 */
054         mov byte ptr [vender_sig + 12], 0;        /* ラストに \0 */
055     }
056 
057     std::cout << "Vender String = " << vender_sig << std::endl;
058 
059 
060     // プロセッサシグネチャ, ファクションフラグ、Featureフラグのチェック
061     DWORD prosessor_sig, function_flag, feature_flag2, feature_flag1;
062     __asm {
063         mov eax, 1;                        /* EAXに1を入れる */
064         cpuid;                            /* CPUID実行 */
065         mov dword ptr [prosessor_sig], eax;    /* プロセッサシグネチャ */
066         mov dword ptr [function_flag], ebx;    /* ファンクションフラグ */
067         mov dword ptr [feature_flag2], ecx;    /* Featureフラグ */
068         mov dword ptr [feature_flag1], edx;    /* Featureフラグ */
069     }
070 
071     // ステッピングID, モデルナンバー, ファミリーコード, プロセッサタイプ
072     DWORD SteppingID, ModelNumder, FamilyCode, ProcessorType;
073     SteppingID =   prosessor_sig & 0x0000000F;
074     ModelNumder =   ( prosessor_sig & 0x000000F0 ) >> 4;
075     FamilyCode =    ( prosessor_sig  & 0x00000F00 ) >> 8;
076     ProcessorType = ( prosessor_sig & 0x000003000 ) >> 12;
077 
078     // マトリックステーブルから一致する文字列を探します。
079     std::string cpustring = "unknown processor";
080     for ( int i = 0 ; ( cpumatrix[i].cpu_code != 0x00 ) ; i++ ) {
081         if ( ( FamilyCode << 4 ) + ModelNumder == cpumatrix[i].cpu_code ) {
082             cpustring = cpumatrix[i].desc;
083         }
084     }
085 
086     std::cout << "ProcessorType = " << ProcessorType << std::endl;
087     std::cout << "SteppingID = " << SteppingID << std::endl;
088     std::cout << "ModelNumder = " << ModelNumder << std::endl;
089     std::cout << "FamilyCode = " << FamilyCode << std::endl;
090     std::cout << "Processor Desciption = [" << cpustring.c_str() << "]" << std::endl;
091 
092     return 0;
093 }

このコードを実行すると、

Vender String = GenuineIntel

ProcessorType = 0

SteppingID = 7

ModelNumder = 4

FamilyCode = 15

Processor Desciption = [Pentium 4 Processor, Pentium D Processor 90um process.]

のように、CPUの情報が出力されることを確認することができます。

posted @ 15:14 | Feedback (30)

Blog 利用状況

コミュニティ

プロファイル