#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#define _8088 0
#define _NECV20 1
#define _80188 2
#define _80286 3
#define _80386 4
char *CPUStrings[] =
{
"8088/8086",
"NEC V20/V30",
"80188/80186",
"80286",
"80386"
};
int CPUInfo( void )
{
/* ---------------------------------------------------------------- */
/* The following Code distinguishes between 286+ (and above) and */
/* the other chips since 286+ (and above) pushes SP prior to */
/* decrementing its value for a PUSH SP instruction... The earlier */
/* processors will decrement SP first... */
/* ---------------------------------------------------------------- */
__emit__(0x8B,0xDC); /* MOV BX, SP */
__emit__(0x54); /* PUSH SP */
__emit__(0x58); /* POP AX */
__emit__(0x87,0xE3); /* XCHG BX, SP */
if ( _AX == _BX )
{
/* ---------------------------------------------------------------- */
/* The following Code distinguishes between a 286 and higher */
/* processors since the 286 sets bits 12-14 of the FLAGS to zero */
/* after a PUSHF... */
/* ---------------------------------------------------------------- */
__emit__(0xB8,0x00,0x70); /* MOV AX, 7000h */
__emit__(0x50); /* PUSH AX */
__emit__(0x9D); /* POPF */
__emit__(0x9C); /* PUSHF */
__emit__(0x58); /* POP AX */
if ( ( _AX & 0x7000 )==0x0000 )
return( _80286 );
else
return( _80386 );
}
/* ---------------------------------------------------------------- */
/* The Following Code singles out the 80186 and 80188 since the Top */
/* three bits in CL are excluded by a shift instruction on those */
/* processors... i.e. Only the lower 5 bits of CL is used.. Using */
/* the value of 33 in CL is guaranteed to clear the register with */
/* the lower processors.. */
/* ---------------------------------------------------------------- */
__emit__(0xB0, 0xFF); /* MOV AL, 0FFh */
__emit__(0xB1, 0x21); /* MOV CL, 21h */
__emit__(0xD2, 0xE8); /* SHR AL, CL */
if ( _AL != 0x00 )
return( _80188 );
/* ---------------------------------------------------------------- */
/* The NEC V20/V30 carry forth a string instruction with REP and */
/* segment override even when Interrupts are enabled (unlike the */
/* 8088/8086)... */
/* ---------------------------------------------------------------- */
enable(); /* Ensure int's enabled */
__emit__(0x56); /* PUSH SI */
__emit__(0xB9,0xFF,0xFF); /* MOV CX, 0FFFFh */
__emit__(0xF3,0x26,0xAC); /* REP LODS BPTR ES:[SI]*/
__emit__(0x5E); /* POP SI */
if ( _CX == 0x00 )
return( _NECV20 );
return( _8088 );
}
int main(void)
{
printf("CPU Detection Routine\n");
printf("--- --------- -------\n\n");
printf("Current Processor is: %s\n\n", CPUStrings[ CPUInfo() ]);
return( 0 );
}