📄 cpuid.c
字号:
** This function detects whether the processor and operating* system both support Pentium III Instructions.** Inputs: none** Returns:* 0 = CPU or OS does not support Pentium III Instructions* else CPU and OS support Pentium III Instuctions ****************************************************************/WORD winknisupport() { DWORD features; features = wincpufeatures(); //Print extra line in message for Pentium III Instruction support, ie, features(25)=1 if (features & 0x02000000) { // Test first for Pentium III support bit // If so, test a KNI instruction and make sure you don't get // an exception (this tests OS support) //__try{ EXECSSE(); //}#if 0 __asm{ //pushad; orps xmm1,xmm1; //Below are the op codes for this instruction //emits will compile w/ MSVC 5.0 compiler //You can comment these out and uncomment the //orps when using the Intel Compiler //__emit 0x0f //__emit 0x56 //__emit 0xc9 //popad; } }#endif // If OS creates an exception, it doesn't support Pentium III Instructions //__except(1) { // return FALSE; } return TRUE; } else return FALSE;}//winknisupport()/**************************************************************** winwilsupport()** This function detects whether the processor and operating* system both support SSE2 Instructions.** Inputs: none** Returns:* 0 = CPU or OS does not support SSE2 Instructions* else CPU and OS support SSE2 Instuctions ****************************************************************/WORD winwilsupport() { DWORD features; features = wincpufeatures(); //Print extra line in message for SSE2 Instruction support, ie, features(26)=1 // Test first for Willamette support bit // If so, test a SSE instruction and make sure you don't get // an exception (this tests OS support) //__try { EXECSSE2();#if 0 __asm{ // pushad; xorpd xmm0,xmm0; //SSE2 Instructions // __emit 0x0f // __emit 0x56 // __emit 0xc9 // popad; }#endif } // If OS creates an exception, it doesn't support SSE2 Instructions //__except(EXCEPTION_EXECUTE_HANDLER) { // if(_exception_code()==STATUS_ILLEGAL_INSTRUCTION) // return FALSE; //Willamette New Instructions not supported } return TRUE; //SSE2 Instructions are supported}//winwilsupport()/**************************************************************** winrdtsc()** Inputs: none** Returns:* 0 = CPU does not support the time stamp register** Else* Returns a variable of type TIME_STAMP which is composed of * two DWORD variables. The 'High' DWORD contains the upper* 32-bits of the Time Stamp Register. The 'Low' DWORD * contains the lower 32-bits of the Time Stamp Register.** Note: This function also sets the global variable clone_flag***************************************************************/#if 0struct TIME_STAMP winrdtsc() { struct TIME_STAMP timestamp; // Return variable for time // stamp read DWORD features = wincpufeatures(); // Processor Features timestamp.Low = 0; timestamp.High = 0; if ( features & 0x00000010 ) { RDTSC // Read Time Stamp _asm { MOV timestamp.Low, EAX MOV timestamp.High, EDX } } return timestamp;} // winrdtsc#endif// Internal Private Functions ///////////////////////////////////**************************************************************** check_clone()** Inputs: none** Returns:* 1 if processor is clone (limited detection ability)* 0 otherwise***************************************************************/static WORD check_clone(){ short cpu_type=0;/*// Not needed for 64-bit machines#ifndef _M_AMD64 _asm { MOV AX,5555h // Check to make sure this XOR DX,DX // is a 32-bit processor MOV CX,2h DIV CX // Perform Division CLC JNZ no_clone JMP clone no_clone: STC clone: PUSHF POP AX // Get the flags AND AL,1 XOR AL,1 // AL=0 is probably Intel, // AL=1 is a Clone MOV cpu_type, ax } cpu_type = cpu_type & 0x0001;#endif*/ __asm__("movw $0x5555, %%ax;\ xorw %%dx, %%dx;\ movw $0x2, %%cx;\ divw %%cx;\ clc;\ jnz no_clone;\ jmp clone;\ no_clone: stc;\ clone: pushf;\ popw %%ax;\ andb $0x1, %%al;\ xorb $0x1, %%al;":"=a"(cpu_type)); return cpu_type; } // check_clone()/**************************************************************** check_8086()** Inputs: none** Returns: * 0 if processor 8086* 0xffff otherwise***************************************************************/#ifndef _M_AMD64static WORD check_8086(){ WORD cpu_type=0xffff;/*_asm { pushf // Push original FLAGS pop ax // Get original FLAGS mov cx, ax // Save original FLAGS and ax, 0fffh // Clear bits 12-15 in FLAGS push ax // Save new FLAGS value on stack popf // Replace current FLAGS value pushf // Get new FLAGS pop ax // Store new FLAGS in AX and ax, 0f000h // If bits 12-15 are set, then cmp ax, 0f000h // processor is an 8086/8088 mov cpu_type, 0 // Turn on 8086/8088 flag je end_8086 // Jump if processor is 8086/ // 8088 mov cpu_type, 0ffffhend_8086: push cx popf mov ax, cpu_type }*/ __asm__("pushf;\ popw %%ax;\ movw %%ax, %%cx;\ andw $0xfff, %%ax;\ push %%ax;\ popf;\ pushf;\ popw %%ax;\ andw $0xf000, %%ax;\ cmp $0xf000, %%ax;\ movw $0, %0;\ je end_8086;\ movw $0xffff, %0;\ end_8086:\ pushw %%cx;\ popf;\ movw %1, %%ax;":"=r"(cpu_type):"r"(cpu_type)); return cpu_type;} // check_8086()#endif/**************************************************************** check_80286()** Inputs: none** Returns:* 2 if processor 80286* 0xffff otherwise***************************************************************/#ifndef _M_AMD64static WORD check_80286(){ WORD cpu_type=0xffff;/*_asm { pushf pop cx mov bx, cx or cx, 0f000h // Try to set bits 12-15 push cx // Save new FLAGS value on stack popf // Replace current FLAGS value pushf // Get new FLAGS pop ax // Store new FLAGS in AX and ax, 0f000h // If bits 12-15 are clear mov cpu_type, 2 // Processor=80286, turn on // 80286 flag jz end_80286 // If no bits set, processor is // 80286 mov cpu_type, 0ffffhend_80286: push bx popf mov ax, cpu_type }*/ __asm__("pushf;\ popw %%cx;\ movw %%cx, %%bx;\ orw $0xf000, %%cx;\ pushw %%cx;\ popf;\ pushf;\ popw %%ax;\ andw $0xf000, %%ax;\ movw $2, %0;\ jz end_80286;\ movw $0xffff, %0;\ end_80286:\ pushw %%bx;\ popf;\ movw %1, %%ax;":"=r"(cpu_type):"r"(cpu_type)); return cpu_type;} // check_80286()#endif/**************************************************************** check_80386()** Inputs: none** Returns:* 3 if processor 80386* 0xffff otherwise***************************************************************/#ifndef _M_AMD64static WORD check_80386(){ WORD cpu_type=0xffff;/*_asm { mov bx, sp and sp, not 3 pushfd // Push original EFLAGS pop eax // Get original EFLAGS mov ecx, eax // Save original EFLAGS xor eax, 40000h // Flip AC bit in EFLAGS push eax // Save new EFLAGS value on // stack popfd // Replace current EFLAGS value pushfd // Get new EFLAGS pop eax // Store new EFLAGS in EAX xor eax, ecx // Can't toggle AC bit, // processor=80386 mov cpu_type, 3 // Turn on 80386 processor flag jz end_80386 // Jump if 80386 processor mov cpu_type, 0ffffhend_80386: push ecx popfd mov sp, bx mov ax, cpu_type and eax, 0000ffffh }*/ __asm__("movw %%sp, %%bx;\ andw $~0x3, %%sp;\ pushf;\ popl %%eax;\ movl %%eax, %%ecx;\ xorl $0x4000, %%eax;\ push %%eax;\ popf;\ pushf;\ popl %%eax;\ xorl %%ecx, %%eax;\ movw $0x3, %0;\ jz end_80386;\ movw $0xffff, %0;\ end_80386:\ pushl %%ecx;\ popf;\ movw %%bx, %%sp;\ movw %1, %%ax;\ andl $0x0000ffff, %%eax":"=r"(cpu_type):"r"(cpu_type)); return cpu_type;} // check_80386()#endif/**************************************************************** check_IDProc()** Inputs: none** Returns:* CPU Family (i.e. 4 if Intel 486, 5 if Pentium(R) Processor)** Note: This function also sets the global variable clone_flag***************************************************************/static WORD check_IDProc() { int i=0; WORD cpu_type=0xffff; BYTE stepping=0; BYTE model=0; BYTE vendor_id[12]="------------"; BYTE intel_id[12]="GenuineIntel"; CPUID_ARGS ca; ca.eax = 0; CPUIDF(&ca); ((DWORD*)vendor_id)[0] = ca.ebx; ((DWORD*)vendor_id)[1] = ca.edx; ((DWORD*)vendor_id)[2] = ca.ecx; #if 0 _asm { //push ebx // ELP xor eax, eax // Set up for CPUID instruction //CPU_ID // Get and save vendor ID cpuid mov dword ptr vendor_id, ebx mov dword ptr vendor_id[+4], edx mov dword ptr vendor_id[+8], ecx //pop ebx }#endif for (i=0;i<12;i++) { if (!(vendor_id[i]==intel_id[i])) { clone_flag = 1; } } if (ca.eax >= 1) { ca.eax = 1; CPUIDF(&ca); stepping = (BYTE)(ca.eax & 0xF); model = (BYTE)((ca.eax >> 4) & 0xF); cpu_type = (WORD)((ca.eax >> 8) & 0xF); }#if 0 _asm { //push ebx // ELP cmp eax, 1 // Make sure 1 is valid input // for CPUID jl end_IDProc // If not, jump to end xor eax, eax inc eax //CPU_ID // Get family/model/stepping/ // features cpuid mov stepping, al and stepping, 0x0f //0fh and al, 0f0h shr al, 4 mov model, al and eax, 0f00h shr eax, 8 // Isolate family and eax, 0fh mov cpu_type, ax // Set _cpu_type with familyend_IDProc: mov ax, cpu_type //pop ebx }#endif return cpu_type;} // Check_IDProc()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -