VC++のインラインアセンブリを用いてEFLAGSレジスタの値とCPUID命令の使用可否を確認するコードです。EFLAGSレジスタの独特な扱い、詳細についてはネットで調べるとすぐ出てくるかと思います。__asm
を使用しているため、32ビット限定です。
class eflags { private: eflags(unsigned int value) : value(value) {} public: union { unsigned int value; struct { unsigned cf : 1; unsigned r1 : 1; unsigned pf : 1; unsigned r2 : 1; unsigned af : 1; unsigned r3 : 1; unsigned zf : 1; unsigned sf : 1; unsigned tf : 1; unsigned if_ : 1; unsigned df : 1; unsigned of : 1; unsigned iopl : 2; unsigned nt : 1; unsigned r4 : 1; unsigned rf : 1; unsigned vm : 1; unsigned ac : 1; unsigned vif : 1; unsigned vip : 1; unsigned id : 1; unsigned r5 : 10; } bits; }; // EFLAGSを読み込む。 static eflags pop() { unsigned int i; __asm { pushfd pop i } return eflags(i); } // EFLAGSを書き込む。 void push() { unsigned int i = value; __asm { push i popfd } } // CPUID命令が有効かどうかを確認する。 static bool is_cpuid_valid() { eflags eflags1 = eflags::pop(); eflags1.bits.id = ~eflags1.bits.id; eflags1.push(); eflags eflags2 = eflags::pop(); eflags2.bits.id = ~eflags2.bits.id; // 元に戻しておく eflags2.push(); return eflags1.value != eflags2.value; } }; #include <iostream> #include <bitset> int main() { std::cout << "CPUID命令は" << (eflags::is_cpuid_valid() ? "有効" : "無効") << "です。" << std::endl; std::cout << "EFLAGS: " << std::bitset<32>(eflags::pop().value) << std::endl; std::cin.get(); return 0; }