CPUID

CPUIDは、x86の機械語命令の一つ（およびそのアセンブリ・ニーモニック）である。CPUの識別 (IDentification) の意。486の後期のステッピングで導入され、Pentiumで完全に公開された。
CPUIDを使用することで、ソフトウェアはプロセッサの形式と機能（例えば、MMXやSSEなどの拡張のサポートの有無）を識別することができる。機械語オペコードは0FA2hであり、オペランドとしてEAXレジスタの値でどのような情報を取得するかを指定する。
CPUID命令の使用可否.
CPUID命令は一部の80486およびそれ以降のプロセッサで利用できるため、場合によってはCPUID命令が存在するプロセッサであるか否かを事前に判別する必要が生じる。80486以前のプロセッサを識別する必要がある場合には、それぞれの振舞の微妙な違いを利用する難解なテクニックを駆使する必要があった（たとえばcodice_1の結果として、codice_2による変化前と変化後の、どちらの値がプッシュされるか、等）。
80486以上のプロセッサであることが確認できた場合、CPUID命令の存在を確認するためのフラグとして32ビットフラグレジスタ (EFLAGS) の第21ビットが新たに設けられているため、このビットが「変更可能」であればCPUID命令が使用可能であると判断できる。なおEFLAGSは80386以上のプロセッサであればアクセスできるため、80286以下のプロセッサを判別・除外しておく必要はあるものの、CPUID命令の有無だけを調べたいのであれば実質的に80386以上であることが確認できればこのフラグを調べることができる。
CPUID命令の呼び出し.
CPUID命令は、EAXレジスタが暗黙のオペランドであり、それ以外の（明示的な）オペランドは無い。どのような情報を返すべきかを指定する値をEAXレジスタに設定し、CPUID命令を実行する。まずcodice_3でCPUIDを呼び出し、CPUでサポートされている最大のパラメータを取得するべきである。CPUIDの拡張機能情報を取得する場合は、EAXのビット31をセットしてCPUIDを呼び出す。拡張機能情報でサポートされている最大の機能番号を得るためには、codice_4でCPUIDを呼び出す。
EAX=0: ベンダIDの取得.
これは、CPUベンダのID文字列を返す。12文字のASCII文字列がEBX, EDX, ECXの順序で格納される。基本機能の最大機能番号がEAXに格納される。
既知のCPUベンダのID文字列は以下のとおり：
例えば、ベンダ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に格納される情報のフォーマットは以下のとおり:
インテルとAMDは、CPUのファミリーを上記の「ファミリー」と「拡張ファミリー」の合計で表示し、モデルを上記の「モデル」と4ビット左シフトした「拡張モデル」の合計で表示するように提案した。
プロセッサ情報と機能フラグはメーカ個別のものであるが、通常は互換性のためにインテルの値を他のメーカも使用している。
また、80386以上のプロセッサではリセット直後のDXレジスタにはこれらの情報（拡張ファミリ・拡張ステッピングは除く）に相当する値が格納されているため、ハード構成によっては80286がプロテクトモードからリアルモードに戻るためのリセット機構（通例、80386以降のシステムでも互換性のために残されている）を利用することで、386/486系プロセッサでもファミリ・モデル・ステッピングなどに相当する情報を得られる場合がある。詳細はIntel 80286およびIntel 80386を参照。
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終端ASCII文字列のプロセッサブランド文字列を得るために、各パラメータを順番に設定し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に格納する。