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の情報が出力されることを確認することができます。
投稿日時 : 2008年3月27日 15:14