home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / cpu / cpuid / cpuid.asm next >
Assembly Source File  |  1991-05-02  |  7KB  |  206 lines

  1.     TITLE    CPUID
  2.     DOSSEG
  3.     .model    small
  4.  
  5.     .stack    100h
  6.  
  7.     .data
  8. fp_status    dw    ?
  9. id_mess     db    "This system has a$"
  10. fp_8087        db    " and an 8087 math coprocessor$"
  11. fp_80287    db    " and an i287tm math coprocessor$"
  12. fp_80387    db    " and an i387tm math coprocessor$"
  13. c8086        db    "n 8086/8088 microprocessor$"
  14. c286        db    "n 80286 microprocessor$"
  15. c386        db    " i386tm microprocessor$"
  16. c486        db    " i486tm DX microprocessor or i487tm SX math coprocessor$"
  17. c486nfp     db    " i486tm SX microprocessor$"
  18. period        db    ".$",13,10
  19. present_86    dw    0
  20. present_286    dw    0
  21. present_386     dw    0
  22. present_486     dw    0
  23.  
  24. ;
  25. ;    The purpose of this code is to allow the user the ability to identify the processor and coprocessor
  26. ;    that is currently in the system.  The algorithm of the program is to first determine the processor 
  27. ;    id.  When that is accomplished, the program continues to then identify whether a coprocessor
  28. ;    exists in the system.  If a coprocessor or integrated coprocessor exists, the program will identify
  29. ;    the coprocessor id.  If one does not exist, the program then terminates.
  30. ;    
  31.     .code
  32. start:
  33.         mov    ax,@data
  34.         mov    ds,ax                ; set segment register
  35.  
  36.         mov    dx,offset id_mess            ; print header message
  37.         mov    ah,9h
  38.         int    21h
  39.  
  40. ;
  41. ;    8086 CPU check
  42. ;    Bits 12-15 are always set on the 8086 processor.
  43. ;    
  44.         pushf                    ; save EFLAGS
  45.         pop    bx                ; store EFLAGS in BX
  46.         mov    ax,0fffh                ; clear bits 12-15
  47.         and    ax,bx                ;    in EFLAGS
  48.         push    ax                ; store new EFLAGS value on stack
  49.         popf                    ; replace current EFLAGS value
  50.         pushf                    ; set new EFLAGS
  51.         pop    ax                ; store new EFLAGS in AX 
  52.         and    ax,0f000h            ; if bits 12-15 are set, then CPU
  53.         cmp    ax,0f000h            ;     is an 8086/8088 
  54.         mov    dx,offset c8086            ; store 8086/8088 message
  55.         mov     present_86,1            ; turn on 8086/8088 flag
  56.         je    check_fpu            ; if CPU is 8086/8088, check for 8087
  57.  
  58. ;
  59. ;    80286 CPU check
  60. ;    Bits 12-15 are always clear on the 80286 processor.
  61. ;
  62.  
  63.         or    bx,0f000h            ; try to set bits 12-15
  64.         push     bx
  65.         popf
  66.         pushf
  67.         pop    ax
  68.         and    ax,0f000h            ; if bits 12-15 are cleared, then CPU
  69.         mov    dx,offset c286            ;    is an 80286
  70.         mov     present_86,0                       ; turn off 8086/8088 flag
  71.         mov     present_286,1                 ; turn on 80286 flag
  72.         jz    check_fpu            ; if CPU is 80286, check for 80287
  73.     
  74. ;
  75. ;    i386 CPU check
  76. ;    The AC bit, bit #18, is a new bit introduced in the EFLAGS register on the i486 DX CPU to 
  77. ;    generate alignment faults.  This bit can be set on the i486 DX CPU, but not on the i386 CPU.
  78. ;
  79.  
  80.         mov    bx,sp                ; save current stack pointer to align it
  81.         and    sp,not 3                ; align stack to avoid AC fault
  82.         db    66h
  83.         pushf                    ; push original EFLAGS
  84.         db    66h
  85.         pop    ax                ; get original EFLAGS 
  86.         db    66h
  87.         mov    cx,ax                ; save original EFLAGS
  88.         db    66h                ; xor EAX,40000h
  89.         xor    ax,0                ; flip AC bit in EFLAGS
  90.         dw    4                ; upper 16-bits of xor constant
  91.         db    66h
  92.         push    ax                ; save for EFLAGS
  93.         db    66h
  94.         popf                    ; copy to EFLAGS
  95.         db    66h
  96.         pushf                    ; push EFLAGS
  97.         db    66h
  98.         pop    ax                ; get new EFLAGS value
  99.         db    66h
  100.         xor    ax,cx                ; if AC bit cannot be changed, CPU is
  101.         mov     dx,offset c386            ; store i386 message
  102.         mov     present_286,0            ; turn off 80286 flag
  103.         mov     present_386,1            ; turn on i386 flag
  104.         je    check_fpu               ; if CPU is i386, now check for                                 ;    80287/80387 MCP
  105.  
  106. ;
  107. ;    i486 DX CPU / i487 SX MCP and i486 SX CPU checking
  108. ;
  109.         mov     dx,offset c486nfp            ; store 486NFP message
  110.         mov     present_386,0            ; turn off i386 flag
  111.         mov     present_486,1            ; turn on i486 flag
  112.  
  113. ;
  114. ;    Co-processor checking begins here for the 8086/80286/i386 CPUs.
  115. ;    The algorithm is to determine whether or not the floating-point status and control words can be 
  116. ;    written to.  If they are not, no coprocessor exists.  If the status and control words can be written
  117. ;    to, the correct coprocessor is then determined depending on the processor id.  Coprocessor 
  118. ;    checks are first performed for an 8086, 80286 and a i486 DX CPU.  If the coprocessor id is still
  119. ;    undetermined, the system must contain a i386 CPU.  The i386 CPU may work with either
  120. ;    an 80287 or an 80387.  The infinity of the coprocessor must be checked to determine the correct
  121. ;    coprocessor id. 
  122. ;
  123.  
  124. check_fpu:                            ; check for 8087/80287/80387
  125.         fninit                    ; reset FP status word
  126.         mov     fp_status,5a5ah            ; initialize temp word to non-zero value
  127.         fnstsw     fp_status            ; save FP status word
  128.         mov    ax,fp_status            ; check FP status word
  129.         cmp     al,0                ; see if correct status with written
  130.         jne     print_one            ; jump if not Valid, no NPX installed
  131.         
  132.                 fnstcw     fp_status        ; save FP control word
  133.                 mov     ax,fp_status        ; check FP control word 
  134.                 and     ax,103fh        ; see if selected parts looks OK
  135.                 cmp     ax,3fh            ; check that ones and zeroes correctly read
  136.                 jne     print_one        ; jump if not Valid, no NPX installed
  137.  
  138.         cmp    present_486,1            ; check if i486 flag is on
  139.         je     is_486                ; if so, jump to print 486 message
  140.         jmp     not_486                ;     else continue with 386 checking
  141.  
  142. is_486:
  143.         mov     dx,offset c486            ; store i486 message
  144.         jmp     print_one
  145.  
  146. not_486:        
  147.         cmp     present_386,1            ; check if i386 flag is on
  148.         jne     print_87_287            ; if i386 flag not on, check NPX for
  149.                             ;    8086/8088/80286
  150.         mov    ah,9h                ; print out i386 CPU ID first
  151.         int    21h
  152.  
  153. ;
  154. ;   80287/80387 check for the i386 CPU
  155. ;
  156.         fld1                    ; must use default control from FNINIT
  157.         fldz                    ; form infinity
  158.         fdiv                    ; 8087/80287 says +inf = -inf
  159.         fld    st                ; form negative infinity
  160.         fchs                    ; 80387 says +inf <> -inf
  161.         fcompp                    ; see if they are the same and remove them
  162.         fstsw     fp_status            ; look at status from FCOMPP
  163.         mov    ax,fp_status
  164.         mov     dx,offset fp_80287        ; store 80287 message
  165.         sahf                    ; see if infinities matched
  166.         jz     restore_EFLAGS            ; jump if 8087/80287 is present
  167.         mov     dx,offset fp_80387        ; store 80387 message
  168.  
  169. restore_EFLAGS:
  170.         mov    ah,9h                ; print NPX message
  171.         int    21h
  172.         db    66h
  173.         push    cx                ; push ECX
  174.         db    66h
  175.         popf                    ; restore original EFLAGS register
  176.         mov    sp,bx                ; restore original stack pointer
  177.         jmp     exit
  178.  
  179. print_one:
  180.         mov    ah,9h                ; print out CPU ID with no NPX
  181.         int    21h
  182.         jmp     exit
  183.         
  184. print_87_287:
  185.         mov    ah,9h                ; print out 8086/8088/80286 first
  186.         int    21h
  187.         cmp     present_86,1            ; if 8086/8088 flag is on
  188.         mov     dx,offset fp_8087        ; store 8087 message
  189.         je     print_fpu
  190.         mov     dx,offset fp_80287        ; else CPU=80286, store 80287 message
  191.  
  192. print_fpu:
  193.         mov    ah,9h                ; print out NPX
  194.         int    21h
  195.         jmp     exit
  196.         
  197. exit:
  198.         mov    dx,offset period            ; print out a period to end message
  199.         mov    ah,9h
  200.         int    21h
  201.  
  202.         mov     ax,4c00h            ; terminate program
  203.         int     21h
  204.  
  205.         end    start
  206.