programmers resources
  http://www.intel-assembler.it/  (c)2017 intel-assembler.it   info@intel-assembler.it
 
Search :  
Lingua Italiana    English Language   
Index
 
just an empty assembly space
just an arrow Intel Platform
just an arrow Article & Guides
just an arrow Download Software


23/01/2009 Featured Article: How to remove Buzus Virus (permalink)




:::3097551:::
Bottone Scambio Directory Pubblicitaonline.it
Home Page | Articles & Guides | Download | Intel Platform | Contacts

Google
 


Bookmark and Share
Download 
Tell a friend



CPUID3 an Intel CPU detection program

Interesting src code for detecting different Cpus

(by intel corporation)

A very interesting assembly code that shows how to distinguish different CPU versions including model and family. The asm source is well commented.
This article is online from 2547 days and has been seen 6179 times





;       Filename:       cpuid32.msm
;
;       This program has been developed by Intel Corporation.  You have
;       Intel's permission to incorporate this source code into your
;       product royalty free.
;
;       Intel specifically disclaims all warranties, express or implied,
;       and all liability, including consequential and other indirect
;       damages, for the use of this code, including liability for
;       infringement of any proprietary rights.  Intel does not assume
;       any responsibility for any errors which may appear in this code
;       nor any responsibility to update it.
;
;       This program contains three parts:
;       Part 1: Identifies CPU type in the variable cpu_type:
;               0=8086 processor
;               2=Intel 286 processor
;               3=Intel386(TM) processor
;               4=Intel486(TM) processor
;               5=Pentium(TM) processor
;
;       Part 2: Identifies FPU type in the variable fpu_type:
;               0=FPU not present
;               1=FPU present
;               2=287 present (only if cpu_type=3)
;               3=387 present (only if cpu_type=3)
;
;       Part 3: Prints out the appropriate message.  This part can
;               be removed if this program is not used in a DOS-based
;               system.  Portions affected are at the end of the
;               data segment and the print procedure in the code
;               segment.
;
;       REVISION HISTORY:
;       Date:  4/93
;       1. Replaced the .486 with .186 to avoid generation of 0FH type long
;          conditional branches (such as the branch to end_get_cpuid at
;          the end of the 8086/8088 test, near code address 003D).  These
;          are not executable on the 8086/8088 and 80286, so the code falls
;          into some strange place and hangs the system.  The .186 also allows
;          multi-bit shifts to unpack CPUID info.  Using .186 requires 
;          that all 32-bit operand prefix (66H) be inserted by hand.  
;          This is done with a macro (OPND32).
;       2. Avoid all usage of 32-bit operands until it is clear that the
;          CPU is at least an 80386.  The use of the Exx registers caused 
;          the generation of the 66H prefix, which are not executed 
;          correctly on the 8086/8088 and 80286.  
;       3. Eliminated all the register save/restore and added comment 
;          that all registers are used by the functions.
;       4. Do the stack alignment just before messing with the AC bit in
;          EFLAGS, otherwise the stack may not be properly aligned.  Also
;          restore the AC bit immediately, so it does not stay set.
;       5. Changed the FPU detection to set one flag fpu_type (instead of
;          the previous two flags: fpu_present and infinity).  An fpu_type
;          of zero indicates no floating point unit is present, an fpu_type
;          of 2 indicates an 80287 is present, an fpu_type of 3 indicates
;          an 80387 is present.
;
;       If this code is assembled with MASM with no options specified, it
;       runs correctly on an 8086/8088, 80286, 80386, 80486, and 
;       Pentium(tm) processor.
;


TITLE   CPUID
DOSSEG
.model  small
.stack  100h
.186

OPND32 MACRO op_code, op_erand
db      66h     ; Force 32-bit operand size
  IFNB <op_code>
db      op_code
    IFNB <op_erand>
dd      op_erand; 32-bit immediate value
    ENDIF
  ENDIF
ENDM

CPUID MACRO
db      0fh     ; Hardcoded opcode for CPUID instruction
db      0a2h
ENDM

TRUE            equ     1
FAMILY_MASK     equ     0f00h
FAMILY_SHIFT    equ     8
MODEL_MASK      equ     0f0h
MODEL_SHIFT     equ     4
STEPPING_MASK   equ     0fh
FPU_FLAG        equ     1h
MCE_FLAG        equ     80h
CMPXCHG8B_FLAG  equ     100h

.data
fp_status       dw      ?
vendor_id       db      12 dup (?)
cpu_type        db      ?
modell           db      ?
stepping        db      ?
id_flag         db      0
fpu_type        db      0
intel_proc      db      0
feature_flags   dw      2 dup (0)
;
; remove the remaining data declarations if not using the DOS-based
; print procedure
;
id_msg          db      "This system has a$"
fp_8087         db      " and an 8087 math coprocessor$"
fp_80287        db      " and an 80287 math coprocessor$"
fp_80387        db      " and an 80387 math coprocessor$"
c8086           db      "n 8086/8088 processor$"
c286            db      "n 80286 processor$"
c386            db      "n 80386 processor$"
c486            db      "n 80486 DX processor or 80487 SX math coprocessor$"
c486nfp         db      "n 80486 SX processor$"
Intel486_msg    db      13,10,"Genuine Intel486(TM) processor",13,10,"$"
Pentium_msg     db      13,10,"Genuine Intel Pentium(TM)  processor",13,10,"$"
modelmsg        db      "Model:            $"
steppingmsg     db      "Stepping:         $"
familymsg       db      13,10,"Processor Family: $"
period          db      ".",13,10,"$"
dataCR          db      ?,13,10,"$"
intel_id        db      "GenuineIntel"
fpu_msg         db      13,10,"This processor contains a FPU",13,10,"$"
mce_msg         db      "Supported Machine Check Exception",13,10,"$"
cmp_msg         db      "Supported CMPXCHG8B instruction",13,10,"$"
not_intel       db      "t least an 80486 processor.",13,10
db      "Not a Genuine Intel part and as a result,",13,10
db      "Detection impossible at this time.",13,10,"$"

;
;       The purpose of this code is to identify the processor and
;       coprocessor that is currently in the system.  The program first
;       determines the processor id.  When that is accomplished,
;       the program then determines whether a coprocessor
;       exists in the system.  If a coprocessor or integrated
;       coprocessor exists, the program identifies
;       the coprocessor id.  The program then prints out
;       the CPU and floating point presence and type.
;
.code
start:  mov     ax, @data
mov     ds, ax          ; set segment register
mov     es, ax          ; set segment register
pushf                   ; save for restoration at end
call    get_cpuid
call    get_fpuid
call    print
popf
mov     ax, 4c00h       ; terminate program
int     21h


get_cpuid proc
;
;       This procedure determines the type of CPU in a system
;       and sets the cpu_type variable with the appropriate
;       value.
;       All registers are used by this procedure, none are preserved.

;       Intel 8086 CPU check
;       Bits 12-15 of the FLAGS register are always set on the
;       8086 processor.
;
check_8086:
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 CPU
cmp     ax, 0f000h      ;   is an 8086/8088
mov     cpu_type, 0     ; turn on 8086/8088 flag
jne     check_80286     ; jump if CPU is not 8086/8088
jmp     end_get_cpuid
;       Intel 286 CPU check
;       Bits 12-15 of the FLAGS register are always clear on the
;       Intel 286 processor in real-address mode.
;
check_80286:
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 clear, CPU=80286
mov     cpu_type, 2     ; turn on 80286 flag
jnz     check_80386     ; if no bits set, CPU is 80286
jmp     end_get_cpuid
;       Intel386 CPU check
;       The AC bit, bit #18, is a new bit introduced in the EFLAGS
;       register on the Intel486 DX CPU to generate alignment faults.
;       This bit cannot be set on the Intel386 CPU.
;
check_80386:
;       It is now safe to use 32-bit opcode/operands
mov     bx, sp          ; save current stack pointer to align
and     sp, not 3       ; align stack to avoid AC fault
OPND32
pushf                   ; push original EFLAGS
OPND32
pop     ax              ; get original EFLAGS
OPND32
mov     cx, ax          ; save original EFLAGS
OPND32  35h, 40000h     ; flip AC bit in EFLAGS
OPND32
push    ax              ; save new EFLAGS value on stack
OPND32
popf                    ; replace current EFLAGS value
OPND32
pushf                   ; get new EFLAGS
OPND32
pop     ax              ; store new EFLAGS in EAX
OPND32
xor     ax, cx          ; can't toggle AC bit, CPU=80386
mov     cpu_type, 3     ; turn on 80386 CPU flag
mov     sp, bx          ; restore original stack pointer
jz      end_get_cpuid   ; jump if 80386 CPU
and     sp, not 3       ; align stack to avoid AC fault
OPND32
push    cx
OPND32
popf                    ; restore AC bit in EFLAGS first
mov     sp, bx          ; restore original stack pointer

;       Intel486 DX CPU, Intel487 SX NDP, and Intel486 SX CPU check
;       Checking for ability to set/clear ID flag (Bit 21) in EFLAGS
;       which indicates the presence of a processor
;       with the ability to use the CPUID instruction.
;
check_80486:
mov     cpu_type, 4     ; turn on 80486 CPU flag
OPND32
mov     ax, cx          ; get original EFLAGS
OPND32  35h, 200000h    ; flip ID bit in EFLAGS
OPND32
push    ax              ; save new EFLAGS value on stack
OPND32
popf                    ; replace current EFLAGS value
OPND32
pushf                   ; get new EFLAGS
OPND32
pop     ax              ; store new EFLAGS in EAX
OPND32
xor     ax, cx          ; can't toggle ID bit,
je      end_get_cpuid   ;   CPU=80486

;       Execute CPUID instruction to determine vendor, family,
;       model and stepping.
;
check_vendor:
mov     id_flag, 1              ; set flag indicating use of CPUID inst
OPND32
xor     ax, ax                  ; set up input for CPUID instruction
CPUID                           ; macro for CPUID instruction
OPND32
mov     word ptr vendor_id, bx  ; setup to test for vendor id
OPND32
mov     word ptr vendor_id[+4], dx
OPND32
mov     word ptr vendor_id[+8], cx
mov     si, offset vendor_id
mov     di, offset intel_id
mov     cx, length intel_id
compare:
repe    cmpsb                   ; compare vendor id to "GenuineIntel"
or      cx, cx
jnz     end_get_cpuid           ; if not zero, not an Intel CPU,

intel_processor:
mov     intel_proc, 1

cpuid_data:
OPND32
cmp     ax, 1                   ; make sure 1 is a valid input
; value for CPUID
jl      end_get_cpuid           ; if not, jump to end
OPND32
xor     ax, ax                  ; otherwise, use as input to CPUID
OPND32
inc     ax                      ; and get stepping, model and family
CPUID
mov     stepping, al
and     stepping, STEPPING_MASK ; isolate stepping info

and     al, MODEL_MASK          ; isolate model info
shr     al, MODEL_SHIFT
mov     modell, al

and     ax, FAMILY_MASK         ; mask everything but family
shr     ax, FAMILY_SHIFT
mov     cpu_type, al            ; set cpu_type with family

OPND32
mov     feature_flags, dx       ; save feature flag data

end_get_cpuid:
ret
get_cpuid endp


;******************************************************************

get_fpuid proc
;
;       This procedure determines the type of FPU in a system
;       and sets the fpu_type variable with the appropriate
;       value.
;       All registers are used by this procedure, none are preserved.

;       Coprocessor check
;       The algorithm is to determine whether the floating-point
;       status and control words can be written to.  If not, no
;       coprocessor exists.  If the status and control words can be
;       written to, the correct coprocessor is then determined
;       depending on the processor id.  The Intel386 CPU can
;       work with either an Intel287 NDP or an Intel387 NDP.
;       The infinity of the coprocessor must be
;       checked to determine the correct coprocessor id.

fninit                  ; reset FP status word
mov     fp_status, 5a5ah; initialize temp word to
; non-zero value
fnstsw  fp_status       ; save FP status word
mov     ax, fp_status   ; check FP status word
cmp     al, 0           ; see if correct status with
; written
mov     fpu_type, 0     ; no fpu present
jne     end_get_fpuid

check_control_word:
fnstcw  fp_status       ; save FP control word
mov     ax, fp_status   ; check FP control word
and     ax, 103fh       ; see if selected parts
; looks OK
cmp     ax, 3fh         ; check that 1's & 0's
; correctly read
mov     fpu_type, 0
jne     end_get_fpuid
mov     fpu_type, 1

;
;   80287/80387 check for the Intel386 CPU
;
check_infinity:
cmp     cpu_type, 3
jne     end_get_fpuid
fld1                    ; must use default control from FNINIT
fldz                    ; form infinity
fdiv                    ; 8087 and Intel287 NDP say +inf = -inf
fld     st              ; form negative infinity
fchs                    ; Intel387 NDP says +inf <> -inf
fcompp                  ; see if they are the same and remove them
fstsw   fp_status       ; look at status from FCOMPP
mov     ax, fp_status
mov     fpu_type, 2     ; store Intel287 NDP for fpu type
sahf                    ; see if infinities matched
jz      end_get_fpuid   ; jump if 8087 or Intel287 is present
mov     fpu_type, 3     ; store Intel387 NDP for fpu type
end_get_fpuid:
ret
get_fpuid endp


;*********************************************************************

print proc
;
;       This procedure prints the appropriate cpuid string and
;       numeric processor presence status.  If the CPUID instruction
;       was supported, this procedure prints out cpuid info.
;       All registers are used by this procedure, none are preserved.

cmp     id_flag, 1              ; if set to 1, cpu supports
;   CPUID instruction
; print detailed CPUID information
jne     cont
jmp     print_cpuid_data

cont:   mov     dx, offset id_msg       ; print initial message
mov     ah, 9h
int     21h

print_86:
cmp     cpu_type, 0
jne     print_286
mov     dx, offset c8086
mov     ah, 9h
int     21h
cmp     fpu_type, 0
jne     cont2
jmp     end_print
cont2:  mov     dx, offset fp_8087
mov     ah, 9h
int     21h
jmp     end_print

print_286:
cmp     cpu_type, 2
jne     print_386
mov     dx, offset c286
mov     ah, 9h
int     21h
cmp     fpu_type, 0
jne     cont3
jmp     end_print
cont3:  mov     dx, offset fp_80287
mov     ah, 9h
int     21h
jmp     end_print

print_386:
cmp     cpu_type, 3
jne     print_486
mov     dx, offset c386
mov     ah, 9h
int     21h
cmp     fpu_type, 0
jne     cont4
jmp     end_print
cont4:  cmp     fpu_type, 2
jne     print_387
mov     dx, offset fp_80287
mov     ah, 9h
int     21h
jmp     end_print

print_387:
mov     dx, offset fp_80387
mov     ah, 9h
int     21h
jmp     end_print

print_486:
cmp     fpu_type, 0
je      print_Intel486sx
mov     dx, offset c486
mov     ah, 9h
int     21h
jmp     end_print

print_Intel486sx:
mov     dx, offset c486nfp
mov     ah, 9h
int     21h
jmp     end_print

print_cpuid_data:

cmp_vendor:
cmp     intel_proc, 1
je      cont5
jmp     not_GenuineIntel
cont5:  cmp     cpu_type, 4                     ; if cpu_type=4, print
; Intel486 CPU message
jne     check_Pentium
mov     dx, offset Intel486_msg
mov     ah, 9h
int     21h
jmp     print_family

check_Pentium:
cmp     cpu_type, 5                     ; if cpu_type=5, print
jne     print_features                  ; Pentium processor message
mov     dx, offset Pentium_msg
mov     ah, 9h
int     21h

print_family:
mov     dx, offset familymsg            ; print family msg
mov     ah, 9h
int     21h
mov     al, cpu_type
mov     byte ptr dataCR, al
add     byte ptr dataCR, 30h            ; convert to ASCII
mov     dx, offset dataCR               ; print family info
mov     ah, 9h
int     21h

print_model:
mov     dx, offset modelmsg             ; print model msg
mov     ah, 9h
int     21h
mov     al, modell
mov     byte ptr dataCR, al
add     byte ptr dataCR, 30h            ; convert to ASCII
mov     dx, offset dataCR               ; print model info
mov     ah, 9h
int     21h

print_stepping:
mov     dx, offset steppingmsg          ; print stepping msg
mov     ah, 9h
int     21h
mov     al, stepping
mov     byte ptr dataCR, al
add     byte ptr dataCR, 30h            ; convert to ASCII
mov     dx, offset dataCR               ; print stepping info
mov     ah, 9h
int     21h

print_features:
mov     ax, feature_flags
and     ax, FPU_FLAG                    ; check for FPU
jz      check_MCE
mov     dx, offset fpu_msg
mov     ah, 9h
int     21h

check_MCE:
mov     ax, feature_flags
and     ax, MCE_FLAG                    ; check for MCE
jz      check_CMPXCHG8B
mov     dx, offset mce_msg
mov     ah, 9h
int     21h

check_CMPXCHG8B:
mov     ax, feature_flags
and     ax, CMPXCHG8B_FLAG              ; check for CMPXCHG8B
jz      end_print
mov     dx, offset cmp_msg
mov     ah, 9h
int     21h
jmp     end_print

not_GenuineIntel:
mov     dx, offset not_Intel
mov     ah, 9h
int     21h

end_print:
ret
print endp

end     start




Top
Download 
Tell a friend
Bookmark and Share



Similar Articles

386ID Four ways to identify your CPU model
Commented assembly source code
(by Bob Smith - Qualitas)

An asm source code for Linux. Hello World
A 59 byte
(by Brian Raiter)

Command Line Process Viewer/Killer/Suspender
CLI utility to manage processes and CPU affinity
(by Craig.Peacock@beyondlogic.org)

CPU-Z v1.51
A good utility for info on you CPU, mobo and RAM
(by CPUID)

Fastclock source code C / Asm
Coding on 8259 timer for high precision clock
(by unknown)

Leggi e Scrivi in Console
Esempio di codice per leggere e scrivere in consol
(by JES)

Make sound from the speaker using assembly
8253, 8255, 8284 program example in asm
(by William Cravener)

Simple Horizontal Scroller
Asm code for scrolling text in vga
(by Carlos Hasan)

Sorgente ASM true.asm
An asm source code for Linux
(by Brian Raiter http://www.muppetlabs.com/~)

TIMING CODE MODULE (80x86 specific code)
Setting pc timer 8259 - Commented source code
(by Ethan Rohrer)

Uso rapido del CPUID
Esempio di codice per l'istruzione MMX CPUID
(by JES)

x86 chksum.asm source code
8 bit Checksum (CRC) Calculation Utility/Sample
(by Erdogan Tan)

 Tags: easy source, cpu


webmaster jes
writers rguru, tech-g, aiguru, drAx

site optimized for IE/Firefox/Chrome with 1024x768 resolution

Valid HTML 4.01 Transitional


ALL TRADEMARKS ® ARE PROPERTY OF LEGITTIMATE OWNERS.
© ALL RIGHTS RESERVED.

hosting&web - www.accademia3.it

grossocactus
find rguru on
http://www.twitter.com/sicurezza3/
... send an email ...
Your name

Destination email

Message

captcha! Code