Perlでアセンブリプログラミングしているとき、実行マシンのCPUを判別してプログラムの処理を分岐したいときがでてくると思います。
そういうときに困ってしまわないように Acme::x86::CPUID を作ってみました。
package Acme::x86::CPUID;
use DynaLoader;
sub ProcessorBrandString {
my $cpu = "\0" x 48;
my $x86 = ""
. "S\xbf" . pack("P", $cpu)
. "\xb8\x02\x00\x00\x80"
. ("P\x0f\xa2\x89\x07\x89_\x04\x89O\x08\x89W\x0c\x8d\x7f\x10X\x8d\@\x01" x 3)
. "[\xc3"
;
DynaLoader::dl_install_xsub("X",unpack"L",pack"P",$x86);&X;
$cpu =~ s/\0+//g;
$cpu =~ s/^ +//;
$cpu;
}
### print Acme::x86::CPUID::ProcessorBrandString, "\n";
1;
DynaLoaderはPerlコアに標準でバンドルされているとっても便利なモジュールです。
※ Acme::x86::CPUID は 100% Pure Perl で書かれているため、別途CコンパイラやXSモジュールなどをインストールする必要がありません。
■ 実行結果
以下、手元にある複数の環境で Acme::x86::CPUID::ProcessorBrandString の値を調べてみました。
※ Linux/Windows/FreeBSDのx86環境でそれぞれ動作確認しましたが、それ以外の環境ではシステムがクラッシュする可能性がありますので実行はお勧めしません。
1. WindowsXP(32bit) - ブログを書いているDELLデスクトップ
Intel(R) Pentium(R) 4 CPU 3.40GHz
2. CentOS5.2(i386) - wafful.org で使用しているVPSレンタルサーバ
Intel(R) Xeon(R) CPU E5430 @ 2.66GHz
3. CentOS4.4(x86_64) - Linux/AMD64 の開発環境
AMD Opteron(tm) Processor 240 EE
4. FreeBSD(i386) - 奥さんから借りている jail 環境
Intel(R) Pentium(R) 4 CPU 3.20GHz
うまく CPU の情報を取ってこれているみたいですね!
■ まとめ
次回Shibuya.pmで発表の機会があれば、この辺の DynaLoader を活用した基礎的なテクニックを簡単にお話ししようと思います。
XS Niteよりも低レベルな内容ですので、Perlや正規表現に詳しくない人でも安心して聞けると思います。どうぞご安心ください。