CPUID
CPUIDオペコードは、x86アーキテクチャの機械語命令の一つである(この名前はCPUの識別 (IDentification) に由来する)。この命令は1990年代にインテルによって486チップの後期のステッピングで導入され、Pentiumプロセッサで完全に公開された[1]。
CPUIDオペコードを使用することで、ソフトウェアはプロセッサの形式と機能(例えば、MMX/SSE命令など)を識別することが出来る。CPUIDオペコードの値は0FA2hであり、EAXレジスタの値でどのような情報を取得するかを指定する。
CPUID命令が使用可能になるまで、プログラマはプロセッサのモデルを区別するために、CPUの振る舞いの微妙な違いを利用する難解な機械語を使用していた[2][3]。
CPUID命令の呼び出し [編集]
アセンブリ言語では、CPUIDは暗黙にEAXレジスタを使用するので、CPUID命令ではパラメータは使用しない。EAXレジスタはどのような情報を返すべきかを指定する値を保持する必要がある。まずEAX = 0でCPUIDを呼び出し、CPUでサポートされている最大のパラメータを取得するべきである。CPUIDの拡張機能情報を取得する場合は、EAXのビット31をセットしてCPUIDを呼び出す。拡張機能情報でサポートされている最大の機能番号を得るためには、EAX = 8000000hでCPUIDを呼び出す。
EAX=0: ベンダIDの取得 [編集]
これは、CPUベンダのID文字列を返す。12文字のASCII文字列がEBX, EDX, ECXの順序で格納される。基本機能の最大機能番号がEAXに格納される。
既知のCPUベンダのID文字列は以下のとおり:
- "AMDisbetter!" - AMD K5の初期のエンジニアリングサンプル
- "AuthenticAMD" - AMD
- "CentaurHauls" - セントールテクノロジー
- "CyrixInstead" - サイリックス
- "GenuineIntel" - インテル
- "GenuineTMx86", "TransmetaCPU" - トランスメタ
- "Geode by NSC" - ナショナル セミコンダクター
- "NexGenDriven" - NexGen
- "RiseRiseRise" - Rise Technology
- "SiS SiS SiS " - SiS
- "UMC UMC UMC " - UMC
- "VIA VIA VIA " - VIA Technologies
例えば、ベンダIDが"GenuineIntel"の場合、EBXが0x756e6547、EDXが0x49656e69、ECXが0x6c65746eとなる。
.section .data s0: .string "Largest Standard Function Number Supported: %i\n" s1: .string "Vendor ID: %s\n" .text .global main .type main, @function main: pushq %rbp movq %rsp, %rbp subl %eax, %eax cpuid subq $8, %rsp movl %ebx, (%rsp) movl %edx, 4(%rsp) movl %ecx, 8(%rsp) movl $s0, %edi movl %eax, %esi subl %eax, %eax call printf movq $s1, %rdi movq %rsp, %rsi subl %eax, %eax call printf subl %eax, %eax movq %rbp, %rsp popq %rbp ret
EAX=1: プロセッサ情報とプロセッサの機能 [編集]
これはCPUのステッピング、モデル、ファミリーをEAXに返す(これはCPUのシグネチャとも呼ばれる)。また、機能フラグをEDXとECXに、追加の機能情報をEBXに返す。
EAXに格納される情報のフォーマットは以下のとおり:
- 3:0 - ステッピング
- 7:4 - モデル
- 11:8 - ファミリー
- 13:12 - プロセッサタイプ
- 19:16 - 拡張モデル
- 27:20 - 拡張ファミリー
インテルとAMDは、CPUのファミリーを上記のファミリーと拡張ファミリーの合計で表示し、モデルを上記のモデルと4ビット左シフトした拡張モデルの合計で表示するように提案した。
プロセッサ情報と機能フラグはメーカ個別のものであるが、通常は互換性のためにインテルの値を他のメーカも使用している。
EAX=2: キャッシュとTLBディスクリプタ情報 [編集]
これは、キャッシュとTLBの機能を示すディスクリプタのリストをEAX, EBX, ECX, EDXレジスタに格納する。
EAX=3: プロッセッサ・シリアル・ナンバ [編集]
これは、プロセッサのシリアル番号を返す。プロセッサ・シリアル・ナンバは、インテルがPentium IIIで導入したが、プライバシーの懸念のためにこの後のモデルでは実装されていない(PSN機能ビットは常にクリアされている)。トランスメタのEfficeonとCrusoeプロセッサはこの機能を提供している。AMDは、この機能をどのCPUにも実装しなかった。
インテルPentium IIIでは、シリアル番号はEDX:ECXレジスタに格納される。トランスメタのEfficeonではEBX:EAXレジスタに、CrusoeではEBXレジスタだけに格納される。
プロセッサ・シリアル・ナンバ機能を使用するためには、BIOSの設定を有効にする必要があることに注意すべきである。
.section .data s0: .string "Processor serial number: %.4hX-%.4hX-%.4hX-%.4hX-%.4hX-%.4hX\n" .text .global main .type main, @function main: pushq %rbp movq %rsp, %rbp movl $1, %eax cpuid subq $4, %rsp movl %eax, (%rsp) movq 2(%rsp), %rbx movw %bx, (%rsp) movw %ax, 2(%rsp) movl $3, %eax cpuid movl %edx, 4(%rsp) movq 6(%rsp), %rax movw %ax, 4(%rsp) movw %dx, 6(%rsp) movl %ecx, 8(%rsp) movl $s0, %edi movw (%rsp), %si movw 2(%rsp), %dx movw 4(%rsp), %cx movw 6(%rsp), %r8w movw 8(%rsp), %r8w movw 10(%rsp), %r9w movw %r9w, (%rsp) subl %eax, %eax call printf subl %eax, %eax movq %rbp, %rsp popq %rbp ret
EAX=80000000h: サポートする最大拡張機能番号の取得 [編集]
最大の拡張機能番号をEAXに格納する。
EAX=80000001h: 拡張プロセッサ情報とプロセッサの機能 [編集]
拡張機能フラグをEDXとECXに格納する。
EAX=80000002h,80000003h,80000004h: プロセッサブランド文字列 [編集]
プロセッサブランド文字列をEAX, EBX, ECX, EDXに格納する。全体で48バイトのNULL終端アスキー文字列のプロセッサブラント文字列を得るために、各パラメータを順番に設定しCPUIDを呼び出す必要がある。
.section .data s0: .string "Processor Brand String: %s\n" .text .global main .type main, @function main: pushq %rbp movq %rsp, %rbp subq $44, %rsp movl $0x80000002, %eax cpuid movl %eax, (%rsp) movl %ebx, 4(%rsp) movl %ecx, 8(%rsp) movl %edx, 12(%rsp) addq $16, %rsp movl $0x80000003, %eax cpuid movl %eax, (%rsp) movl %ebx, 4(%rsp) movl %ecx, 8(%rsp) movl %edx, 12(%rsp) addq $16, %rsp movl $0x80000004, %eax cpuid movl %eax, (%rsp) movl %ebx, 4(%rsp) movl %ecx, 8(%rsp) movl %edx, 12(%rsp) subq $32, %rsp movl $s0, %edi movq %rsp, %rsi subl %eax, %eax call printf subl %eax, %eax movq %rbp, %rsp popq %rbp ret
EAX=80000005h: 予約 [編集]
この機能は使用されていない。
EAX=80000006h: 拡張L2キャッシュ情報 [編集]
ECXにL2キャッシュの詳細情報を格納する。2種類の方法で表したキャッシュサイズと、キャッシュとメモリの対応を示すコードを含む。
.section .data s0: .string "L2 Cache: %iMB\n" .text .global main .type main, @function main: pushq %rbp movq %rsp, %rbp movl $0x80000006, %eax cpuid subl %edx, %edx movl %ecx, (%rsp) movl 2(%rsp), %eax movl $1024, %ecx divl %ecx movl $s0, %edi movl %eax, %esi subl %eax, %eax call printf subl %eax, %eax movq %rbp, %rsp popq %rbp ret
EAX=80000007h: 予約 [編集]
この機能は使用されていない。
EAX=80000008h: 仮想アドレスと物理アドレスのサイズ [編集]
最大の仮想アドレスサイズと物理アドレスサイズをEAXに格納する。
関連項目 [編集]
- Pentium III: プライバシーに関する論争
- CPU-Z、各種のシステム情報を取得するためにCPUIDを使用するウィンドウズユーティリティ
外部リンク [編集]
- http://www.sandpile.org/ia32/cpuid.htm
- http://www.sandpile.org/ -- x86プロセッサの技術的な情報
- CPUID ガイド:
- Windows プログラム:
- DOS プログラム:
- Linux プログラム:
- http://www.etallen.com/cpuid.html
- http://www.ka9q.net/code/cpuid/
- /proc/cpuinfoインタフェースは、他の情報とあわせて、CPUIDからの出力を多く表示する
- Solarisは/dev/cpu/self/cpuidインタフェースを提供している