CPUID

CPUIDは、x86の機械語命令の一つ（およびそのアセンブリ・ニーモニック）である。CPUの識別 (IDentification) の意。486の後期のステッピングで導入され、Pentiumで完全に公開された[1]。 CPUIDを使用することで、ソフトウェアはプロセッサの形式と機能（例えば、MMXやSSEなどの拡張のサポートの有無）を識別することができる。機械語オペコードは0FA2hであり、オペランドとしてEAXレジスタの値でどのような情報を取得するかを指定する。 CPUID命令は一部の80486およびそれ以降のプロセッサで利用できるため、場合によってはCPUID命令が存在するプロセッサであるか否かを事前に判別する必要が生じる。80486以前のプロセッサを識別する必要がある場合には、それぞれの振舞の微妙な違いを利用する難解なテクニックを駆使する必要があった[2][3]（たとえばPUSH SPの結果として、PUSHによる変化前と変化後の、どちらの値がプッシュされるか、等）。 80486以上のプロセッサであることが確認できた場合、CPUID命令の存在を確認するためのフラグとして32ビットフラグレジスタ (EFLAGS) の第21ビットが新たに設けられているため、このビットが「変更可能」であればCPUID命令が使用可能であると判断できる。なおEFLAGSは80386以上のプロセッサであればアクセスできるため、80286以下のプロセッサを判別・除外しておく必要はあるものの、CPUID命令の有無だけを調べたいのであれば実質的に80386以上であることが確認できればこのフラグを調べることができる。 CPUID命令は、EAXレジスタが暗黙のオペランドであり、それ以外の（明示的な）オペランドは無い。どのような情報を返すべきかを指定する値をEAXレジスタに設定し、CPUID命令を実行する。まずEAX = 0でCPUIDを呼び出し、CPUでサポートされている最大のパラメータを取得するべきである。CPUIDの拡張機能情報を取得する場合は、EAXのビット31をセットしてCPUIDを呼び出す。拡張機能情報でサポートされている最大の機能番号を得るためには、EAX = 8000000hでCPUIDを呼び出す。 これは、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 これはCPUのステッピング、モデル、ファミリーをEAXに返す（これはCPUの「シグネチャ」とも呼ばれる）。また、機能フラグをEDXとECXに、追加の機能情報をEBXに返す。 EAXに格納される情報のフォーマットは以下のとおり: 3:0 - ステッピング 7:4 - モデル 11:8 - ファミリー 13:12 - プロセッサタイプ 19:16 - 拡張モデル 27:20 - 拡張ファミリー インテルとAMDは、CPUのファミリーを上記の「ファミリー」と「拡張ファミリー」の合計で表示し、モデルを上記の「モデル」と4ビット左シフトした「拡張モデル」の合計で表示するように提案した。 プロセッサ情報と機能フラグはメーカ個別のものであるが、通常は互換性のためにインテルの値を他のメーカも使用している。 また、80386以上のプロセッサではリセット直後のDXレジスタにはこれらの情報（拡張ファミリ・拡張ステッピングは除く）に相当する値が格納されているため、ハード構成によっては80286がプロテクトモードからリアルモードに戻るためのリセット機構（通例、80386以降のシステムでも互換性のために残されている）を利用することで、386/486系プロセッサでもファミリ・モデル・ステッピングなどに相当する情報を得られる場合がある。詳細はIntel 80286およびIntel 80386を参照。 これは、キャッシュとTLBの機能を示すディスクリプタのリストをEAX, EBX, ECX, EDXレジスタに格納する。 これは、プロセッサのシリアル番号を返す。プロセッサ・シリアル・ナンバは、インテルが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に格納する。 AMD社のCPUの拡張機能フラグをEDXとECXに格納する。 EDXのビット 0 から 9, 12 から 17, 23と 24は、AMDのCPUではEAX=1の場合のCPUIDの結果と重複し、IntelのCPUでは未使用である。IntelのCPUでもsyscall, nx, pdpe1gb, rdtscp, lm, lahf_lm, abm/lzcnt, 3dnowprefetchに対応しているものもある。