home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / 80x0393.zip / CPUID.ASM < prev    next >
Assembly Source File  |  1993-03-30  |  11KB  |  240 lines

  1. TITLE   CPUID
  2. ;v5.93  Toad Hall Tweak, 1 Jul 91
  3. ;       - Tightened up code a little, tabified.
  4. ;         I have *no* idea what he did to make the original
  5. ;         CPUID.EXE 6Kb long!  debug enabled?
  6. ;       - Rewritten to .COM format to reduce size further.
  7. ;       We *really* should be returning a magic number as ERRORLEVEL
  8. ;       so a batch file could process accordingly.
  9. ;       David Kirschbaum
  10. ;       kirschd@sesi.com
  11.  
  12. ;v5.94  DD Tweak, 8 Jan 92, to return errorlevels
  13. ;       This version assembles with Eric Isaacson's A86
  14. ;       Fixed the problem with "period" not always being printed
  15. ;       Doug Dougherty, valley@gsbsun.uchicago.edu
  16.  
  17. CSEG    SEGMENT
  18.         ASSUME  CS:CSEG,DS:CSEG,ES:CSEG
  19.  
  20.         org     100H                    ;.COM file
  21.  
  22. cpuid   proc    near
  23.         jmp     start                   ;skip over data
  24.  
  25. exitcode        db      0               ;v5.94
  26.  
  27. fp_status       dw      0
  28. id_mess         db      "CPUID v5.94 (Toad Hall, DD tweaks)"            ;v5.94
  29.                 db      13,10,13,10,"This system has a$"                ;v5.94
  30. fp_8087         db      " and an 8087 math coprocessor$"
  31. fp_80287        db      " and an i287tm math coprocessor$"
  32. fp_80387        db      " and an i387tm math coprocessor$"
  33. c8086           db      "n 8086/8088 microprocessor$"
  34. c286            db      "n 80286 microprocessor$"
  35. c386            db      " i386tm microprocessor$"
  36. c486            db      " i486tm DX microprocessor or i487tm SX math coprocessor$"
  37. c486nfp         db      " i486tm SX microprocessor$"
  38. period          db      ".",13,10,"$"
  39. present_86      db      0       ;v5.92
  40. present_286     db      0       ;v5.92
  41. present_386     db      0       ;v5.92
  42. present_486     db      0       ;v5.92
  43.  
  44. cpuid   endp
  45.  
  46. ;
  47. ; The purpose of this code is to allow the user the ability to identify the
  48. ; processor and coprocessor that is currently in the system.  The algorithm
  49. ; of the program is to first determine the processor id.
  50. ; When that is accomplished, the program continues to then identify whether
  51. ; a coprocessor exists in the system.  If a coprocessor or integrated
  52. ; coprocessor exists, the program will identify the coprocessor id.  If one
  53. ; does not exist, the program then terminates.
  54. ;
  55. start   proc    near
  56.  
  57.         mov     dx,offset id_mess               ; print header message
  58.         mov     ah,9h
  59.         int     21h
  60.  
  61. ;
  62. ;       8086 CPU check
  63. ;       Bits 12-15 are always set on the 8086 processor.
  64. ;
  65.         mov     cx,0F000H               ;handy constant                 v5.93
  66.         pushf                           ; save EFLAGS
  67.         pop     bx                      ; store EFLAGS in BX
  68.         mov     ax,0fffh                ; clear bits 12-15
  69.         and     ax,bx                   ;       in EFLAGS
  70.         push    ax                      ; store new EFLAGS value on stack
  71.         popf                            ; replace current EFLAGS value
  72.         pushf                           ; set new EFLAGS
  73.         pop     ax                      ; store new EFLAGS in AX
  74.         and     ax,cx   ;0f000h         ; if bits 12-15 are set,        v5.93
  75.         cmp     ax,cx   ;0f000h         ; then CPU is an 8086/8088      v5.93
  76.         mov     dx,offset c8086         ; store 8086/8088 message
  77.         mov     present_86,1            ; turn on 8086/8088 flag
  78.         mov     exitcode,1              ; Setup exitcode for 8086/8088  v5.94
  79.         je      check_fpu               ; if CPU is 8086/8088, check for 8087
  80.  
  81. ;
  82. ;       80286 CPU check
  83. ;       Bits 12-15 are always clear on the 80286 processor.
  84. ;
  85.  
  86.         or      bx,cx   ;0f000h         ; try to set bits 12-15         v5.93
  87.         push    bx
  88.         popf
  89.         pushf
  90.         pop     ax
  91.         and     ax,cx   ;0f000h         ; if bits 12-15 are cleared     v5.93
  92.         mov     dx,offset c286          ; then CPU is an 80286
  93.         mov     present_86,0            ; turn off 8086/8088 flag
  94.         mov     present_286,1           ; turn on 80286 flag
  95.         mov     exitcode,2              ; Setup exitcode for 80286      v5.94
  96.         jz      check_fpu               ; if CPU is 80286, check for 80287
  97.  
  98. ;
  99. ; i386 CPU check
  100. ; The AC bit, bit #18, is a new bit introduced in the EFLAGS register on the
  101. ;  i486 DX CPU to generate alignment faults.  This bit can be set on the
  102. ;  i486 DX CPU, but not on the i386 CPU.
  103.  
  104.  
  105.         mov     bx,sp                   ; save current stack pointer to align it
  106.         and     sp,not 3                ; align stack to avoid AC fault
  107.         db      66h
  108.         pushf                           ; push original EFLAGS
  109.         db      66h
  110.         pop     ax                      ; get original EFLAGS
  111.         db      66h
  112.         mov     cx,ax                   ; save original EFLAGS
  113.         db      66h                     ; xor EAX,40000h
  114.         xor     ax,0                    ; flip AC bit in EFLAGS
  115.         dw      4                       ; upper 16-bits of xor constant
  116.         db      66h
  117.         push    ax                      ; save for EFLAGS
  118.         db      66h
  119.         popf                            ; copy to EFLAGS
  120.         db      66h
  121.         pushf                           ; push EFLAGS
  122.         db      66h
  123.         pop     ax                      ; get new EFLAGS value
  124.         db      66h
  125.         xor     ax,cx                   ; if AC bit cannot be changed, CPU is
  126.         mov     dx,offset c386          ; store i386 message
  127.         mov     present_286,0           ; turn off 80286 flag
  128.         mov     present_386,1           ; turn on i386 flag
  129.         mov     exitcode,3              ; Setup exitcode for 80386      v5.94
  130.         je      check_fpu               ; if CPU is i386, now check for
  131.                                         ;       80287/80387 MCP
  132.  
  133. ;
  134. ;       i486 DX CPU / i487 SX MCP and i486 SX CPU checking
  135. ;
  136.         mov     dx,offset c486nfp       ; store 486NFP message
  137.         mov     present_386,0           ; turn off i386 flag
  138.         mov     present_486,1           ; turn on i486 flag
  139.         mov     exitcode,4              ; Setup exitcode for 80486      v5.94
  140.  
  141. ;
  142. ; Co-processor checking begins here for the 8086/80286/i386 CPUs.
  143. ; The algorithm is to determine whether or not the floating-point status
  144. ; and control words can be written to.  If they are not, no coprocessor exists.
  145. ; If the status and control words can be written to, the correct coprocessor
  146. ; is then determined depending on the processor id.  Coprocessor checks are
  147. ; first performed for an 8086, 80286 and a i486 DX CPU.  If the coprocessor id
  148. ; is still undetermined, the system must contain a i386 CPU.  The i386 CPU may
  149. ; work with either an 80287 or an 80387.  The infinity of the coprocessor must
  150. ; be checked to determine the correct coprocessor id.
  151. ;
  152.  
  153. check_fpu:                              ; check for 8087/80287/80387
  154.         fninit                          ; reset FP status word
  155.         mov     fp_status,5a5ah         ; initialize temp word to non-zero value
  156.         fnstsw  fp_status               ; save FP status word
  157.         mov     ax,fp_status            ; check FP status word
  158. ;v5.93  cmp     al,0
  159.         or      al,al                   ; see if correct status with written v5.93
  160.         jne     print_one               ; jump if not Valid, no NPX installed
  161.  
  162.         fnstcw  fp_status               ; save FP control word
  163.         mov     ax,fp_status            ; check FP control word
  164.         and     ax,103fh                ; see if selected parts looks OK
  165.         cmp     ax,3fh                  ; check that ones and zeroes correctly
  166.                                         ; read
  167.         jne     msgterm                 ; not valid, no NPX installed   v5.93
  168.  
  169.         cmp     present_486,1           ; check if i486 flag is on
  170.         jne     not_486                 ;nope, continue 386 checking    v5.93
  171.                                         ;yep, display i486 msg          v5.93
  172.          mov    dx,offset c486          ; store i486 message
  173.          jmp    msgterm                 ;display i486 message, terminate v5.93
  174.  
  175. not_486:
  176.         cmp     present_386,1           ; check if i386 flag is on
  177.         jne     print_87_287            ; if i386 flag not on, check NPX for
  178.                                         ;       8086/8088/80286
  179.         mov     ah,9h                   ; print out i386 CPU ID first
  180.         int     21h
  181.  
  182. ;
  183. ;   80287/80387 check for the i386 CPU
  184. ;
  185.         fld1                            ; must use default control from FNINIT
  186.         fldz                            ; form infinity
  187.         fdiv                            ; 8087/80287 says +inf = -inf
  188.         fld     st                      ; form negative infinity
  189.         fchs                            ; 80387 says +inf <> -inf
  190.         fcompp                          ; see if they are the same
  191.                                         ; and remove them
  192.         fstsw   fp_status               ; look at status from FCOMPP
  193.         mov     ax,fp_status
  194.         mov     dx,offset fp_80287      ; store 80287 message
  195.         sahf                            ; see if infinities matched
  196.         jz      restore_EFLAGS          ; jump if 8087/80287 is present
  197.          mov    dx,offset fp_80387      ; store 80387 message
  198.  
  199. restore_EFLAGS:
  200.         mov     ah,9h                   ; print NPX message
  201.         int     21h
  202.         db      66h
  203.         push    cx                      ; push ECX
  204.         db      66h
  205.         popf                            ; restore original EFLAGS register
  206.         mov     sp,bx                   ; restore original stack pointer
  207.         jmp     short exit
  208.  
  209. print_one:
  210.         jmp     short msgterm           ;print out CPU ID with no NPX   v5.93
  211.  
  212. print_87_287:
  213.         mov     ah,9h                   ; print out 8086/8088/80286 first
  214.         int     21h
  215.         cmp     present_86,1            ; if 8086/8088 flag is on
  216.         mov     dx,offset fp_8087       ; store 8087 message
  217.         je      print_fpu
  218.         mov     dx,offset fp_80287      ; else CPU=80286, store 80287 message
  219.  
  220. print_fpu:
  221.         or      exitcode,080h           ; High bit => NPX present       v5.94
  222.         jmp     short msgterm           ;print out NPX                  v5.93
  223.  
  224. exit:
  225.         mov     dx,offset period        ; print out a period to end message
  226. msgterm:
  227.         mov     ah,9h
  228.         int     21h
  229.  
  230.         cmp     dx,offset period        ; print out a period to end message v5.94
  231.         jne     exit                    ; (if we have not already done so)
  232.  
  233.         mov     ah,4ch                  ; terminate program
  234.         mov     al,exitcode             ;v5.94
  235.         int     21h
  236. start   endp
  237.  
  238. CSEG    ENDS
  239.         end     cpuid
  240.