CPUってどうやって識別するの?

weekly making now! (99.11.13)

<Home> → <weekly making now!> → <weekly making now! (99.11.13)>


この章は DOS、Windows 9x、Windows NT を対象としています。

CPUってどうやって認識するの?

巷では Hardware を認識したり Benchmark を取ったりするソフトウェアが人気を博しているようです。有名所で言うと以下のソフトウェアです。

これらのソフトウェアはどのようにして CPU を認識、識別をしているのでしょうか?もちろん、Windows の API にも CPU の種類を返してくれる function はあります。しかし、標準の API はかなり poor な機能しか持ってなく、os の version によってもマチマチなので使用されていないのが普通です。実は CPU には自分自身を判別するための命令(opcode)を用意しています。

それが CPUID です。

Before to study CPUID

実際に CPUID を呼び出して CPU を判別してみましょう。
Windows 付属のユーティリティ Debug.exe(ってよりMS-DOS 3.x から付属していてWindows 9x はもとより Windows NT にもあるんだよね>Debug.exe)でも出来ない訳ではないのですが、色々面倒くさいので以下のユーティリティを使って説明します。

それでは早速実習に入ります。

D:\>exdeb <Enter>
Extended Debugger Ver1.85 94,97/07 by Sey_ju_row
CPU [Pentium II] FPU [Present] Machine [PC-98 DOS/V]
-q <Enter>
D:\>

いきなり終了してしまいました (^^;。
「q」は終了するコマンドです。覚えて置きましょう。

Let's study CPUID!

それでは早速 cpuid を実行してみましょう。
ちなみに私の使用している CPU は Intel Pentium II (233MHz)です。言い忘れましたが、念のためすべての program を閉じておいた方が良いでしょう。cpuid をサポートしていない cpu だととてつもない事が、、、(^^;

一応、チェックする方法は下記に示してあります。

D:\>exdeb <Enter>
Extended Debugger  Ver1.85  94,97/07  by Sey_ju_row
CPU [Pentium II]  FPU [Present]  Machine [PC-98 DOS/V]
-r1 <Enter>
EAX=000F:0000    EBX=0000:0000    ECX=0000:0000    EDX=4965:0000
ESP=0000:0000    EBP=0000:0000    ESI=0000:0000    EDI=0000:0000
DS=4121  ES=0000  SS=4121  FS=0000  GS=0000  CS=4121  IP=0100  -N11--I---------
4121:0100 66B800000000   MOV    EAX,00000000
-a

4121:0100       mov eax, 0 <Enter>
4121:0106       cpuid <Enter>
4121:0108       int 3 <Enter>
4121:0109       <Enter>
-g
EAX=0000:0002    EBX=756E:6547    ECX=6C65:746E    EDX=4965:6E69
ESP=0000:0000    EBP=0000:0000    ESI=0000:0000    EDI=0000:0000
DS=4121  ES=0000  SS=4121  FS=0000  GS=0000  CS=4121  IP=0108  -N11--I---------
4121:0108 CC             INT    3
-q <Enter>

D:\>

実行できましたか?

eax を 0 に設定して cpuid を実行すると、各register(eax,ebx,ecx,edx)は以下の値を
返してきます。この値で私の cpu が Intel 製の cpu なのが分かります。
蛇足ですが各 register の値は ASCII コードで表わされています。

eax = 0 の時の cpuid 命令が返す値
各registerの値
Intel 製の場合
AMD 製の場合
Cyrix 製の場合
eax
CPUID の最大入力値
ebx
"Genu"
"Auth"
"Cyri"
ecx
"ineI"
"enti"
"xIns"
edx
"ntel"
"cAMD"
"tead"

次にバージョン情報を取得してみましょう。

D:\>exdeb <Enter>
Extended Debugger  Ver1.85  94,97/07  by Sey_ju_row
CPU [Pentium II]  FPU [Present]  Machine [PC-98 DOS/V]
-r1 <Enter>
EAX=000F:0000    EBX=0000:0000    ECX=0000:0000    EDX=0080:0000
ESP=0000:0000    EBP=0000:0000    ESI=0000:0000    EDI=0000:0000
DS=4121  ES=0000  SS=4121  FS=0000  GS=0000  CS=4121  IP=0100  -N11--I---------
4121:0100 66B801000000   MOV    EAX,00000001
-a <Enter>

4121:0100       mov eax, 1 <Enter>
4121:0106       cpuid <Enter>
4121:0108       int 3 <Enter>
4121:0109       <Enter>
-g <Enter>
EAX=0000:0634    EBX=0000:0000    ECX=0000:0000    EDX=0080:F9FF
ESP=0000:0000    EBP=0000:0000    ESI=0000:0000    EDI=0000:0000
DS=4121  ES=0000  SS=4121  FS=0000  GS=0000  CS=4121  IP=0108  -N11--I---------
4121:0108 CC             INT    3
-q <Enter>

D:\>

今度はどうでしょう。

eax = 1 で cpuid を実行すると以下の値が返ってきます。

通常、バージョン情報で CPU の識別を行ないます。
上記の場合、以下のようになります。

他の CPU については [sandpile.org -- IA-32 architecture -- CPUID] を参照してください。

これ以上説明すると作りかけにならなくなるので止めときます(^^;。
後は「使用した資料」を参照して各々補完してください。

Is support CPUID?

もし CPUID をサポートしていない CPU で CPUID を使用すると、CPU は無効な命令を受け取った事になるわけで、CPU はそれなりの対処をし、os にその後の処理を任せます。Windows ならば一般保護エラー、DOS なら亜空間へ旅経ってしまいます。

実際の所、最近の Intel 製 CPU ではまず CPUID をサポートしていないことはないのですが、Intel互換 CPU ですと、意図的に CPUID をサポートしないように変更できてしまうので注意が必要です。

私が使っている CPUID 判定プログラムを置いておきます。一応、Visual C++ は通るはずです。BC ではチョッチエラーが発生しますがなんとかして (^^;。

BOOL IsCPUID( void );
int main()
{
    if( IsCPUID() ) printf("CPUID is supported!\n");
    else            printf("CPUID can't be supported...\n");
    return 0;
}
BOOL IsCPUID( void )
{
    BOOL result = TRUE;
    _asm{
        pushfd
        pop     eax
        mov     ecx, eax
        xor     eax, 0x200000   ; ID ビット
        push    eax
        popfd
        pushfd
        pop     eax
        and     eax, 0x200000   ; ID ビットがトルクしない
                                ; ---> can't support CPUID
        and     ecx, 0x200000   ; ID ビットがトルクする
                                ; ---> support CPUID
        xor     eax, ecx
        jnz     jSupCPUID
        mov     result, FALSE
jSupCPUID:
    }
    return result;
}

使用した資料

他にも参考になる homepage が多数あるのですが、イチイチ紹介していたのでは作りかけにならないので最低限で留めておきます。

Link
Comment
デベロッパ・ホーム(Intel) Intel 製の CPU ならばここから辿ってください。
PentiumII 一応、私の使っている CPU ということで。
ここの「Pentium(R) IIプロセッサ関連アプリケーション・ノート」のAP-485(AP-485J) に今回説明したCPUID による CPU 判定について述べられています。
さらに「Pentium(R) IIプロセッサ関連マニュアル」に日本語版のマニュアルまであります。
タダってすばらしいっ。
sandpile.org CPUID についてはここが一番詳しいかと思います。

#結構時間かかったなぁ。ノベ4時間って所か?


<Home> → <weekly making now!> → <weekly making now! (99.11.13)>
Copyright (c) 1999 Makoto NARA (Mc.N), Some rights reserved.
This web page is licensed under a Creative Commons License.
Creative Commons License
<Terms of Use>

Valid CSS! Valid HTML 4.01!