www.pudn.com > 测试 CPU和NDP 的型号.zip > CHIPS.ASM


page    60,132 
title   chips() - CPU and Math Coprocessor (NDP) Type Check 
 
;   calling convention: 
; 
;       int chips( void ); 
; 
;   returns: 
; 
;       tucked away neatly in your AX.... 
; 
;       you get back   8x if an 8088/8086 
;                     18x if an 80186/80188 
;                     28x if an 80286 
;                     38x if an 80386 
;                     20x for a NEC V20/V30 
;                AND 
;                     xx0 if NO NDP is found 
;                     xx1 if an 8087 
;                     xx2 if an 80287 
;                     xx3 for an 80387 
; 
;   OR..... 
; 
;   >>> A return of 280 means you got an 80286 machine with no NDP, <<< 
;   >>> 383 means you have an 80386/80387 rig to work with, and a   <<< 
;   >>> return of 81 sez that you have 8088/8086 CPU with an 8087.  <<< 
;   >>> A 200 tells you that you got an NEC V20/V30 without an NDP. <<< 
;   >>> ETC., Etc., etc.                                            <<< 
; 
;   NOTE: 
; 
;       There are lotsa ways of handling the way this function returns 
;       it's data.  For my purposes, I have elected this one because 
;       it requires only int arithmetic on the caller's end to extract 
;       all the info I need from the return value.  I think that I'm 
;       well enough 'commented' in the following code so that you will 
;       be able to tinker and Putz until you find the best return tech- 
;       nique for Ur purposes without having to reinvent the wheel. 
; 
;     >>>>        Please see TEST.C, enclosed in this .ARC.      <<<< 
; 
;   REFERENCES: 
; 
;     _chips is made up of two PROC's, cpu_type and ndp_type. 
; 
;       cpu_type is based on uncopyrighted, published logic by 
;         Clif (that's the way he spells it) Purkiser of Intel - 
;         Santa Clara. 
; 
;       ndp_type is adopted from Ted Forgeron's article in PC 
;         Tech Journal, Aug '87 p43. 
; 
;     In the event of subsequent republication of this function, 
;       please carry forward reference to these two gentlemen as 
;       original authors. 
; 
;       Copr. 1987      Pat Shea - Psi! (that Copr. is on there cuz my 
;                                        lawyer sez I should, but feel 
;                                        free to hack away!!!    pats.) 
; 
 
_text   SEGMENT BYTE PUBLIC 'CODE' 
        ASSUME  CS:_text 
 
        PUBLIC  _chips 
 
_chips         PROC NEAR 
 
control dw     0              ; control word needed for the NDP test 
 
        push   BP             ; save where Ur at 
        mov    BP,SP          ;   going in..... 
        push   DI 
        push   SI 
        push   CX             ; not really needed for MSC but kinda 
                              ;   nice to do cuz someone else might 
                              ;   want to use the function and we do 
                              ;   use CX later on 
 
        call   cpu_type       ; find out what kinda CPU you got and 
                              ;   and save it in DX for future reference 
        call   ndp_type       ; check for math coprocessor (NDP) type 
                              ;   and hold that result in AX 
 
        add    AX,DX          ; add the two results together and hold 
                              ;   'em in AX for Ur return to the caller 
 
        pop    CX             ; put things back the way that you 
        pop    SI             ;   found 'em when you started this 
        pop    DI             ;   little drill off..... 
        pop    BP 
                              ; AND 
        ret                   ; go back to where you came from.... 
                              ;   ( ===>  the calling program ) 
                              ;   with Ur results sittin' in AX !! 
_chips         endp 
 
 
cpu_type       PROC NEAR 
 
        pushf                 ; pump Ur flags register onto the stack 
        xor    DX,DX          ; blow out Ur DX and AX to start off 
        xor    AX,AX          ;   with a clean slate 
        push   AX             ; put AX on the stack 
        popf                  ; bring it back in Ur flags 
        pushf                 ; try to set bits 12 thru 15 to a zero 
        pop    AX             ; get back Ur flags word in AX 
        and    AX, 0f000h     ; if bits 12 thru 15 are set then you got 
        cmp    AX, 0f000h     ;   an Intel 8018x or a 808x or maybe even 
        jz     dig            ;   a NEC V20/V30 ??? - gotta look more... 
 
; OTHERWISE.... 
;   Here's the BIG one.... 'tells the difference between an 80286 and 
;   an 80386 !! 
 
        mov    AX, 07000h     ; try to set FLAG bits 12 thru 14 
                              ;   - NT, IOPL 
        push   AX             ; put it onto the stack 
        popf                  ;   and try to pump 07000H into Ur flags 
        pushf                 ; push Ur flags, again 
        pop    AX             ;   and bring back AX for a compare 
        and    AX,07000h      ; if Ur bits 12 thru 14 are set 
        jnz    got386         ;   then Ur workin' with an 80386 
        mov    DX, 0280       ; save 280 in DX cuz it's an 80286 
        jmp    SHORT CPUbye   ;   and bail out 
 
got386: mov    DX, 0380       ; save 380 in DX cuz it's an Intel 80386 
        jmp    SHORT CPUbye   ;   and bail out 
 
; here's we try to figger out whether it's an 80188/80186, an 8088/8086 
;   or an NEC V20/V30 - 'couple of slick tricks from Clif Purkiser..... 
 
dig:    mov    AX, 0ffffh     ; load up AX 
        mov    CL, 33         ; HERE's the FIRST TRICK.... this will 
                              ;   shift everything 33 times if it's 
                              ;   8088/8086, or once for a 80188/80186! 
        shl    AX, CL         ; on a shift of 33, all bits get zeroed 
        jz     digmor         ;   out so if anything is left ON it's 
                              ;   gotta be an 80188/80186 
        mov    DX,0180        ; save 180 in DX cuz it's an 80188/80186 
        jmp    SHORT CPUbye   ;   and bail out 
 
digmor: xor    AL,AL          ; clean out AL to set ZF 
        mov    AL,40h         ; ANOTHER TRICK.... mul on an NEC duz NOT 
        mul    AL             ;   effect the zero flag BUT on an Intel 
        jz     gotNEC         ;   8088/8086, the zero flag gets thrown 
        mov    DX,0080        ; 80 into DX cuz it's an Intel 8088/8086 
        jmp    SHORT CPUbye   ;   and bail out 
 
gotNEC: mov    DX,0200        ; it's an NEC V20/V30 so save 200 in DX 
 
CPUbye: popf                  ; putchur flags back to where they were 
        ret                   ;   and go back to where you came from 
                              ;   (i.e., ===>  _chips) with the CPU type 
                              ;   tucked away in DX for future reference 
cpu_type       endp 
 
; Check for an NDP. 
; 
; >>>>NOTE:  If you are using an MASM version < 5.0, don't forget to 
; use the /R option or you will bomb cuz of the coprocessor instruc- 
; tions.  /R is not needed for version 5.0.<<<<<<<<<<<<<<<<<<<<<<<<< 
 
ndp_type       PROC NEAR 
 
do_we:  fninit                          ; try to initialize the NDP 
        mov    byte ptr control+1,0     ; clear memory byte 
        fnstcw control                  ; put control word in memory 
        mov    AH,byte ptr control+1    ; iff AH is 03h, you got 
        cmp    AH,03h                   ;   an NDP on board !! 
        je     chk_87                   ; found somethin', keep goin' 
        xor    AX,AX                    ; clean out AX to show a zero 
        jmp    SHORT NDPbye             ;   return (i.e., no NDP) 
 
; 'got an 8087 ?? 
 
chk_87: and    control,NOT 0080h        ; turn ON interrupts (IEM = 0) 
        fldcw  control                  ; load control word 
        fdisi                           ; turn OFF interrupts (IEM = 1) 
        fstcw  control                  ; store control word 
        test   control,0080h            ; iff IEM=1, 8087 
        jz     chk287                   ; 'guess not!  March on.... 
        mov    AX,0001                  ; set up for a 1 return to 
        jmp    SHORT NDPbye             ;   show an 8087 is on board 
 
; if not.... would you believe an 80287 maybe ?? 
 
chk287: finit                 ; set default infinity mode 
        fld1                  ; make infinity 
        fldz                  ;   by dividing 
        fdiv                  ;   1 by zero !! 
        fld    st             ; now make a 
        fchs                  ;   negative infinity 
        fcompp                ; compare Ur two infinities 
        fstsw  control        ; iff, for 8087 or 80287 
        fwait                 ; sit tight 'til status word is put away 
        mov    AX,control     ; getchur control word 
        sahf                  ; putchur AH into flags 
        jnz    got387         ; NO GOOD.... march on !! 
        mov    AX,0002        ; gotta be a 80287 cuz we already tested 
        jmp    SHORT NDPbye   ;   for an 8087 
 
; We KNOW that there is an NDP on board otherwise we would have bailed 
; out after 'do_we'.  It isn't an 8087 or an 80287 or we wouldn't have 
; gotten this far.  It's gotta be an 80387 !! 
 
got387: mov    AX,0003        ; call it an 80387 and return 3 
 
NDPbye: ret                   ; and go back where you came from 
                              ;   (i.e., ===>  _chips) carrying the NDP 
                              ;   type in Ur AX register 
ndp_type       endp 
 
_text   ends 
        end