⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpuid.asm

📁 国外网站上的一些精典的C程序
💻 ASM
字号:
; cpuid.asm;; This module contains a C callable routine which returns a 16-bit; integer (in AX) which indicates the type of CPU on which the; program is running.  The low eight bits (AL) contain a number; corresponding to the family number (e.g. 0 = 8086, 1 = 80186,; 2 = 80286, etc.).  The high eight bits (AH) contain a collection; of bit flags which are defined below.;;       written on Thu  10-31-1996  by Edward J. Beroset;               and released to the public domain by the author;%       .MODEL  memodel,C               ;Add model support via command                                        ;line macros, e.g.                                        ;MASM /Dmemodel=LARGE,                                        ;TASM /Dmemodel=SMALL, etc.        .8086        PUBLIC cpu_id;; using MASM 6.11       Ml /c /Fl CPUID.ASM;; using TASM 4.00       TASM CPUID.ASM;; using older assemblers, you may have to use the following equate; and eliminate the .586 directive;;CPUID equ "dw 0a20fh";; bit flags for high eight bits of return value;HAS_NPU         equ     01hIS386_287       equ     02hIS386SX         equ     04hCYRIX           equ     08hNEC             equ     10hNEXGEN          equ     20hAMD             equ     40hUMC             equ     80h        .codecpu_id  proc        push    bx        push    cx        push    dx        push    bp        mov     bp,sp        xor     dx,dx                   ; result = 0 (UNKNOWN);**********************************************************************; The Cyrix test;;   Cyrix processors do not alter the AF (Aux carry) bit when;   executing an XOR.  Intel CPUs (and, I think, all the others);   clear the AF flag while executing an XOR AL,AL.;;**********************************************************************TestCyrix:        mov     al,0fh                  ;        aas                             ; set AF flag        xor     al,al                   ; only Cyrix leaves AF set        aas                             ;        jnc     Test8086                ;        or      dh,CYRIX                ; it's at least an 80386 clone        jmp     Test486                 ;;**********************************************************************;; The 80186 or under test;;   On <80286 CPUs, the SP register was decremented *before* being;   pushed onto the stack.  All later CPUs do it correctly.; ;**********************************************************************Test8086:        push    sp                      ; Q: is it an 8086, 80188, or        pop     ax                      ;        cmp     ax,bp                   ;        je      Test286                 ;   N: it's at least a 286;**********************************************************************; The V20/V30 test;;   NEC's CPUs set the state of ZF (the Zero flag) correctly after;   a MUL.  Intel's CPUs do not -- officially the state of ZF is;   "undefined" after a MUL or IMUL.;;**********************************************************************TestV20:        xor     al,al                   ; clear the zero flag        mov     al,1                    ;        mul     al                      ;        jnz     Test186                 ;        or      dh,NEC                  ; it's a V20 or a V30;**********************************************************************; The 80186 test;;   On the 80186, shifts only use the five least significant bits,;   while the 8086 uses all 8, so a request to shift 32 bits will;   be requested as a shift of zero bits on the 80186.;;**********************************************************************Test186:        mov     al,01h                  ;        mov     cl,32                   ; shift right by 33 bits        shr     al,cl                   ;        mov     dl,al                   ; al = 0 for 86, al = 1 for 186longTestNpu:        jmp     TestNpu                 ;;**********************************************************************; The 286 test;   Bits 12-15 (the top four) of the flags register are all set to;   0's on a 286 and can't be set to 1's.;;**********************************************************************Test286:        .286        mov     dl,2                    ; it's at least a 286        pushf                           ; save the flags        pop     ax                      ; fetch 'em into AX        or      ah,0f0h                 ; try setting those high bits        push    ax                      ;        popf                            ; run it through the flags reg        pushf                           ;        pop     ax                      ; now check the results        and     ah,0F0h                 ; Q: are bits clear?        jz      longTestNpu             ;   Y: it's a 286;**********************************************************************; The 386 test;;   The AC (Alignment Check) bit was introduced on the 486.  This;   bit can't be toggled on the 386.;;**********************************************************************Test386:        .386        mov     dl,3                    ; it's at least a 386        pushfd                          ; assure enough stack space        cli        and     sp, NOT 3               ; align stack to avoid AC fault        pushfd                          ;        pop     cx                      ;        pop     ax                      ;        mov     bx,ax                   ; save a copy        xor     al,4                    ; flip AC bit        push    ax                      ;        push    cx                      ;        popfd                           ;        pushfd                          ;        pop     cx                      ;        pop     ax                      ;        and     al,4                    ;        sti        xor     al,bl                   ; Q: did AC bit change?        jnz     Test486                 ;   N: it's a 386        .386P;**********************************************************************; The 386SX test;;   On the 386SX, the ET (Extension Type) bit of CR0 is permanently;   set to 1 and can't be toggled.  On the 386DX this bit can be;   cleared.;**********************************************************************        mov     eax,cr0        mov     bl,al                   ; save correct value        and     al,not 10h              ; try clearing ET bit        mov     cr0,eax                 ;        mov     eax,cr0                 ; read back ET bit        xchg    bl,al                   ; patch in the correct value        mov     cr0,eax                 ;        test    bl,10h                  ; Q: was bit cleared?        jz      TestNpu                 ;  Y: it's a DX        or      dh,IS386SX              ;  N: it's probably an SX;**********************************************************************; The 486 test;;   Try toggling the ID bit in EFLAGS.  If the flag can't be toggled,;   it's a 486.;; Note:;   This one isn't completely reliable -- I've heard that the NexGen;   CPU's don't make it through this one even though they have all;   the Pentium instructions.;**********************************************************************Test486:        .486        pushfd        pop     cx        pop     bx        mov     dl,4                    ;        mov     ax,bx                   ;        xor     al,20h                  ; flip EFLAGS ID bit        push    ax                      ;        push    cx                      ;        popfd                           ;        pushfd                          ;        pop     cx                      ;        pop     ax                      ;        and     al,20h                  ; check ID bit        xor     al,bl                   ; Q: did ID bit change?        jz      TestNpu                 ;   N: it's a 486;**********************************************************************; The Pentium+ tests;;   First, we issue a CPUID instruction with EAX=0 to get back the;   manufacturer's name string.  (We only check the first letter.);;**********************************************************************PentPlus:        .586        push    dx                      ;        xor     eax,eax                 ;        cpuid                           ;        pop     dx                      ;        cmp     bl,'G'                  ; Q: GenuineIntel?        jz      WhatPent                ;   Y: what kind?        or      dh,CYRIX                ; assume Cyrix for now        cmp     bl,'C'                  ;        jz      WhatPent                ;        xor     dh,(CYRIX OR AMD)       ;        cmp     bl,'A'                  ;        jz      WhatPent                ;        xor     dh,(AMD OR NEXGEN)      ;        cmp     bl,'N'                  ;        jz      WhatPent                ;        xor     dh,(NEXGEN OR UMC)      ; assume it's UMC        cmp     bl,'U'                  ;        jz      WhatPent                ;        xor     dh,UMC                  ; we don't know who made it!;**********************************************************************; The Pentium+ tests (part II);;   This test simply gets the family information via the CPUID;   instruction;;**********************************************************************WhatPent:        push    edx                     ;        xor     eax,eax                 ;        inc     al                      ;        cpuid                           ;        pop     edx                     ;        and     ah,0fh                  ;        mov     dl,ah                   ; put family code in DL;**********************************************************************; The NPU test;;   We reset the NPU (using the non-wait versions of the instruction, of;   course!), put a non-zero value on the stack, then write the NPU;   status word to that stack location.  Then we check for zero, which;   is what would be there if there were an NPU.;;**********************************************************************TestNpu:        .8087        .8086        mov     sp,bp                   ; restore stack        fninit                          ; init but don't wait        mov     ax,0EdEdh               ;        push    ax                      ; put non-zero value on stack        fnstsw  word ptr [bp-2]         ; save NPU status word        pop     ax                      ;        or      ax,ax                   ; Q: was status = 0?        jnz     finish                  ;   N: no NPu        or      dh,HAS_NPU              ;   Y: has NPU;**********************************************************************; The 386/287 combo test;;   Since the 386 can be paired with either a 387 or 287, we check to;   see if the NPU believes that +infinity equals -infinity.  The 387;   says they're equal, while the 287 doesn't.;;**********************************************************************        cmp     dl,3                    ; Q: is CPU a 386?        jnz     finish                  ;  N: no need to check infinities        fld1                            ; load 1        fldz                            ; load 0        fdiv                            ; calculate infinity! (1/0)        fld     st                      ; duplicate it        fchs                            ; change signs of top inf        fcompp                          ; identical?        push    ax                      ;        fstsw   word ptr [bp-2]         ;        pop     ax                      ;        test    ah,40h                  ; Q: does NPU say they're equal?        jz      finish                  ;  N: it's a 387        or      dh,IS386_287            ;finish:        mov     ax,dx                   ; put our return value in place        pop     bp                      ; clean up stack        pop     dx                      ;        pop     cx                      ;        pop     bx                      ;        ret                             ;cpu_id  endp        END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -