(Assembly source code) to detect the CPU model

Source: Internet
Author: User
Tags exit pop value prefetch

_processor Detection Schemes_
by Richard C. leinecker
[LISTING One]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Detect the Processor Type-by Richard C. leinecker;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_ptext SEGMENT PARA Public ' CODE '
Assume Cs:_ptext, Ds:_ptext
Public _processor
; This routine returns the processor type as an integer value.
; C Prototype
; int Processor (void);
; returns:0 = 8088, 1 = 8086, 2 = 80286, 3 = = 80386, 4 = = 80486
; Code assumes es, AX, BX, CX, and DX can be altered. If their contents
; Must is preserved, then you'll have to push and pop them.
_processor proc Far
Push BP; Preserve bp
MOV bp,sp; bp = sp
Push DS; Preserve DS
Push di; and Di
MOV Ax,cs; Point DS
MOV ds,ax; To _ptext
Call IsItAn8088; Returns 0 or 2
CMP al,2; 2 = 286 or better
Jge AtLeast286; Go to 286 and above code
Call IsItAn8086; Returns 0 or 1
JMP short exitprocessor; Jump to exit code
AtLeast286:
Call IsItA286; If it ' s a 286
CMP al,3; 4 and above for 386 and up
JL Short Exitprocessor; Jump to exit code
AtLeast386:
Call IsItA386; If it ' s a 386
Exitprocessor:
Pop di; Restore di,
Pop ds; Ds
Pop bp; and BP
RET; Return to caller
_processor ENDP
; Is It a 8088?
; Returns ax==0 for 8088/8086, ax==2 for 80286 and above
IsItAn8088 proc
PUSHF; Preserve the Flags
PUSHF; Push the flags So
Pop bx; We can pop them into BX
and BX,00FFFH; Mask off Bits 12-15
Push BX; And put it back on the stack
Popf; Pop value back into the flags
PUSHF; Push it back. 8088/8086 would
; Have bits 12-15 set
Pop bx; Get value into BX
and bx,0f000h; Mask all but bits 12-15
Sub Ax,ax; Set Ax to 8088 value
CMP bx,0f000h; If the bits are still set
Je Not286; Jump if not
MOV al,2; Set for 286 and above
Not286:
Popf; Restore the Flags
RET; Return to caller
IsItAn8088 ENDP
; Is It a 8086?
; Returns ax==0 for 8088, ax==1 for 8086
; Code takes advantage of the 8088 ' s 4-byte prefetch queues and 8086 ' s
; 6-byte prefetch queues. By self-modifying the code at a location exactly 5
; Bytes away from IP, and determining if the modification took effect,
; You can differentiate between 8088s and 8086s.
IsItAn8086 proc
MOV Ax,cs; Es = = Code segment
MOV Es,ax
STD; Cause STOSB to count backwards
MOV dx,1; DX is flag and we ' ll start at 1
mov Di,offset Endlabel; Di==offset of code tail to modify
MOV al,090h; al==nop instruction OpCode
MOV cx,3; Set for 3 repetitions
REP STOSB; Store the bytes
CLD; Clear the direction flag
NOP; Three Nops in a row
NOP; Provide dummy instructions
Nop
Dec DX; Decrement flag (only with 8088)
NOP; Dummy instruction--6 bytes
Endlabel:
Nop
MOV ax,dx; Store the flag in AX
RET; Back to Caller
IsItAn8086 ENDP
; Is It a 80286?
; Determines whether processor is a 286 or higher. Going into subroutine ax = 2
; If The processor is a 386 or higher, Ax would be 3 before returning. The
; Method are to set AX to 7000h which represent the 386/486 NT and IOPL bits
; This is pushed onto the stack and popped to the flags (with Popf).
; The flags are then pushed back onto the stack (with PUSHF). Only a 386 or 486
; Would keep the 7000h bits set. If it ' s a 286, those bits aren ' t defined and
; When the flags are pushed onto stack, these bits would be 0. Now, when the ax is
; Popped these bits can be checked. If they ' re set, we have a 386 or 486.
IsItA286 proc
PUSHF; Preserve the Flags
MOV ax,7000h; Set the NT and IOPL flag
; BITS only available for
; 386 processors and above
Push ax; Push Ax so we can pop 7000h
; into the flag register
Popf; Pop 7000h off of the stack
PUSHF; Push the flags back on
Pop ax; Get the pushed flags
; into ax
and ah,70h; If the NT and IOPL
; Flags are still set
MOV ax,2; Set AX to the 286 value
JZ YesItIsA286; If NT and IOPL not set
; It ' s a 286
Inc. AX; Ax now are 4 to indicate
; 386 or higher
YesItIsA286:
Popf; Restore the Flags
RET; Return to caller
IsItA286 ENDP
; Is It an 80386 or 80486?
; Determines whether processor is a 386 or higher. Going into subroutine ax=3
; If The processor is a 486, Ax would be 4 before leaving. The method was to set
; The AC bit of the flags via EAX and the stack. If It stays set, it ' s a 486.
IsItA386 proc
MOV di,ax; Store the processor value
MOV bx,sp; Save SP
and sp,0fffch; Prevent alignment fault
.386
PUSHFD; Preserve the Flags
PUSHFD; Push so we can get flags
Pop eax; Get flags into EAX
or eax,40000h; Set the AC bit
push eax; Push back on the stack
POPFD; Get the value into flags
PUSHFD; Put the value back on stack
Pop eax; Get value into EAX
Test eax,40000h; If the bit is set
JZ YesItIsA386; If not we have a 386
Add di,2; Increment to indicate 486
YesItIsA386:
POPFD; Restore the Flags
.8086
MOV sp,bx; Restore SP
MOV ax,di; Put processor value into ax
RET; Back to Caller
IsItA386 ENDP
_ptext ENDS
End
[LISTING Two]
.586
; Pentium detect routine. Call only after verifying processor be an i486 or
; Later. Returns 4 If i486, 5 if Pentium, 6 or greater for future
; Intel processors.
ef_idequ200000h; ID bit in EFlags register
Pentium proc Near
; Check for Pentium or later by attempting to toggle the ID bit in EFlags reg;
; If we can ' t, it ' s an i486.
PUSHFD; Get Current Flags
Popeax;
Movebx,eax;
xoreax,ef_id; Attempt to toggle ID bit
Pusheax;
POPFD;
PUSHFD; Get new EFlags
Popeax;
PUSHEBX; Restore Original Flags
POPFD;
andeax,ef_id; If we couldn ' t toggle ID, it ' s an i486
andebx,ef_id;
CMPEAX,EBX;
Jeshort Is486;
; It ' s a Pentium or later. Use CPUID to get processor family.
moveax,1; Get processor Info form of CPUID
CPUID;
shrax,8; Get Family field; 5 means Pentium.
ANDAX,0FH;
Ret
Is486:
movax,4; Return 4 for i486
Ret
Pentium ENDP
[LISTING THREE]
#pragma inline
Main ()
{
Long Start1;
Long End1;
Long Start2;
Long End2;
Start1 = Clock ();
ASM P386
ASM mov eax,10000000
ASM Lea EBX,LOOP1
ASM LOOP1:
ASM Dec EAX
ASM JZ LOOP1E
ASM JMP EBX
LOOP1E:
Start2 = End1 = Clock ();
ASM mov eax,10000000
ASM Lea EBX,LOOP2
ASM NOP
ASM LOOP2:
ASM Dec EAX
ASM JZ LOOP2E
ASM JMP EBX
LOOP2E:
End2 = Clock ();
printf ("misaligned loop time =%d, aligned loop time =%d
",
(int) (END1-START1), (int) (END2-START2));
Return
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.