目次

ニュース

日記カテゴリ

書庫

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
Feedback
  • # re: インラインアセンブラ使ってみようぜ CPUID
    スーパーあんどちん
    Posted @ 2008/03/27 16:13
    あむどがぁ…
    さいりっくすがぁ…
    とらんすめたがぁ…

    いや、まぁ別にいいんですけど。
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/27 16:23
    もちろん、CPU対応表作ればできますが^-^;

    >さいりっくすがぁ…
    ザイリンクスに見えた。そろそろ重症かも orz
  • # re: インラインアセンブラ使ってみようぜ CPUID
    とっちゃん
    Posted @ 2008/03/27 17:01
    Pentium 4 と D が 90 um になってます。
    大きさが違う気がします。
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/27 17:18
    むしろ、仕様書が↓こうなっていてどれがどれやら^-^;

    0xF3
    Pentium 4 processor, Intel Xeon processor, Intel Celeron D processor.
    All processors are model 03h and manufactured using the 90 nm process.

    0xF4
    Pentium 4 processor, Pentium 4 processor Extreme Edition, Pentium D
    processor, Intel Xeon processor, Intel Xeon processor MP, Intel Celeron D
    processor. All processors are model 04h and manufactured using the 90 nm process.

    0xF6
    Pentium 4 processor, Pentium D processor, Pentium processor Extreme Edition,
    Intel Xeon processor, Intel Xeon processor MP, Intel Celeron D processor. All processors are model
    06h and manufactured using the 65 nm proces
  • # re: インラインアセンブラ使ってみようぜ CPUID
    とっちゃん
    Posted @ 2008/03/27 17:42
    んと、0xF4 だけ、90um になってるですよw

    できれば、90nmくらいの大きさにしてくれると
    ATXのケースにおさまりきるんではないかと...w


    ってことで本題w
    0xF3 は、初代プレスコットのIDです。
    0xF4 は、改訂版ですね。初代より若干熱効率が良くなってます(ステップが違う)。
    0xF6 は、65nm 版なので、最後のネットバーストアーキテクチャですね。

    0xF0~0xF2もそれぞれ開発コードネームがありますよw
    忘れちゃったけどwww<おい!
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/27 17:46
    ほんとだ。マイクロメーターになってました。
    これじゃげじげじCPU並みですね。

    しかし、NetburstのファミリはなんでFにしちゃったんでしょうね。それほど最終形態に近い自負があったんでしょうかw
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/27 17:49
    >0xF0~0xF2もそれぞれ開発コードネームがありますよw
    Willamette, Northwoodかな?
  • # re: インラインアセンブラ使ってみようぜ CPUID
    とっちゃん
    Posted @ 2008/03/27 19:05
    おー。そんな感じの名前w

    よく覚えてるなぁ...
  • # re: インラインアセンブラ使ってみようぜ CPUID
    774RR
    Posted @ 2008/03/27 19:14
    なんかこれは性分なんだろうけど typo がどーしても気になる
    > 上記の命令を実行すると、ASCII文字列で、GeniureIntelという文字が
    返ってこねえよ!
  • # re: インラインアセンブラ使ってみようぜ CPUID
    中博俊
    Posted @ 2008/03/27 21:26
    複数CPUの場合どうなるの?
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/27 21:40
    >とっちゃん
    northwoodだけ覚えていてましたよ。
    当時北森とか呼ばれてたし。

    >774RRさん
    どのように記述したら納得されますか?

    >中さん
    GetProcessAffinityMaskっていうWin32APIを・・使ったら意味がないですね。
    現在のところは勘弁してください。
  • # re: インラインアセンブラ使ってみようぜ CPUID
    774RR
    Posted @ 2008/03/27 22:48
    GeniureIntel は返ってこないと思う
    GenuineIntel なら納得
    ところでいまどきあまりいないと思うけど i386 はどーしよう。
  • # re: インラインアセンブラ使ってみようぜ CPUID
    とっちゃん
    Posted @ 2008/03/27 23:14
    たしか、2000って i386 はサポートしていなかったと思います。
    なので、考慮しなくてもいいと思うんですけど。

    486(無印)すら対応していなかった気がします。

    VC8以降、公式には 2000 以降のOSしかサポートしてないですから。

    9x系まで広げても95ですら、386をサポートしていたかどうか怪しいですし...w
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/28 8:23
    言及してないですけど、i386はCPUID命令自体をサポートしてません。486SX以降のみ対応ですね。

  • # re: インラインアセンブラ使ってみようぜ CPUID
    774RR
    Posted @ 2008/03/28 8:44
    うん。なので eflags のチェックを行わずに
    いきなし CPUID を実行するってのは俺的には抵抗があるの。
    Win32 配下では i386 がありえないのであればいきなしも可かな?
    ちうことで i386 の話を振ってみた次第
  • # re: インラインアセンブラ使ってみようぜ CPUID
    ながせ
    Posted @ 2008/03/28 8:50
    確かに業務で使うとか、ソフトウェアを売ります公開しますだとすると、↑のソースじゃまずいんですけどね。

    SSE命令とか拡張使うんであれば、そうでなくてもチェックしないとまずいですね。
タイトル
名前
Url
コメント 

Blog 利用状況

コミュニティ

プロファイル