CPUIDは、x86機械語命令の一つ(およびそのアセンブリ・ニーモニック)である。CPUの識別 (IDentification) の意。486の後期のステッピングで導入され、Pentiumで完全に公開された[1]

CPUIDを使用することで、ソフトウェアはプロセッサの形式と機能(例えば、MMXSSEなどの拡張のサポートの有無)を識別することができる。機械語オペコードは0FA2hであり、オペランドとしてEAXレジスタの値でどのような情報を取得するかを指定する。

CPUID命令が使用可能になるまでは、プロセッサの識別には、それぞれの振舞の微妙な違いを利用する難解なテクニックを駆使する必要があった[2][3](たとえば「PUSH SP」の結果として、PUSHによる変化前と変化後の、どちらの値がプッシュされるか、等)。

CPUID命令の呼び出し編集

CPUID命令は、EAXレジスタが暗黙のオペランドであり、それ以外の(明示的な)オペランドは無い。どのような情報を返すべきかを指定する値をEAXレジスタに設定し、CPUID命令を実行する。まずEAX = 0でCPUIDを呼び出し、CPUでサポートされている最大のパラメータを取得するべきである。CPUIDの拡張機能情報を取得する場合は、EAXのビット31をセットしてCPUIDを呼び出す。拡張機能情報でサポートされている最大の機能番号を得るためには、EAX = 8000000hで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に格納される情報のフォーマットは以下のとおり:

  • 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終端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に格納する。

関連項目編集

外部リンク編集