AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > 汇编语言

侦测CPU型号

51自学网 2015-09-08 http://www.51zixue.net

_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 be 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        ; See 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        ; See 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 an 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 will
                                                ; 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       ; See 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 an 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 an 80286?
; Determines whether processor is a 286 or higher. Going into subroutine ax = 2
; If the processor is a 386 or higher, ax will be 3 before returning. The
; method is to set ax to 7000h which represent the 386/486 NT and IOPL bits
; This value is pushed onto the stack and popped into the flags (with popf).
; The flags are then pushed back onto the stack (with pushf). Only a 386 or 486
; will 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 will be 0. Now, when 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          ; see 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 is 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 will be 4 before leaving. The method is 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      ; See 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 is an i486 or
; later. Returns 4 if on i486, 5 if Pentium, 6 or greater for future
; Intel processors.
EF_ID equ 200000h  ; 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
 pop eax   ;
 mov ebx,eax   ;
 xor eax,EF_ID ; attempt to toggle ID bit
 push eax   ;
 popfd    ;
 pushfd   ; get new EFLAGS
 pop eax   ;
 push ebx  ; restore original flags
 popfd    ;
 and eax,EF_ID ; if we couldn't toggle ID, it's an i486
 and ebx,EF_ID  ;
 cmp eax,ebx   ;
 je short Is486  ;

; It's a Pentium or later. Use CPUID to get processor family.
 mov eax,1  ; get processor info form of CPUID
 cpuid    ;
 shr ax,8  ; get Family field;  5 means Pentium.
 and ax,0Fh   ;
 ret
Is486:
 mov ax,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/n",
    (int)(end1-start1), (int)(end2-start2));
    return;
}  

 

 

 
上一篇:The 808 Virus  下一篇:CIH V1.5版本病毒源码