home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / stdlib.zip / CPUTYPE.ASM < prev    next >
Assembly Source File  |  1990-08-13  |  12KB  |  172 lines

  1. ;-----------------------------------------------------------------------------
  2. ; CPU_Type determines the CPU type in the system.                               
  3. ;-----------------------------------------------------------------------------  
  4. ; Written by:                                                                   
  5. ;   Robert Collins                                                              
  6. ;   3361 Keys Lane                                                              
  7. ;   Anaheim, CA  92804                                                          
  8. ;-----------------------------------------------------------------------------  
  9. ; Input:   None                                                                 
  10. ; Output:  AX = CPU type                                                        
  11. ;           0 = 8086/8088                                                       
  12. ;           1 = 80186/80188                                                     
  13. ;           2 = 80286                                                           
  14. ;           3 = 80386                                                           
  15. ;           4 = 80486                                                           
  16. ;        FFFF = Unknown CPU type                                                
  17. ;-----------------------------------------------------------------------------  
  18.                                                                                 
  19.         .radix 16       ; anybody that programs in base 10 is a wimp!   
  20.         .386P           ; MASM 5.1 directive                            
  21.                                         
  22. ;-----------------------------------------------------------------------------  
  23. ; PUBLIC statements here                                                        
  24. ;-----------------------------------------------------------------------------  
  25.         Public  sl_CPU_Type                                                        
  26.                                         
  27. ;-----------------------------------------------------------------------------  
  28. ; Local variable definitions                                                    
  29. ;-----------------------------------------------------------------------------  
  30.  
  31. INT6        equ     [bp-4]                                                  
  32.                                         
  33. ;-----------------------------------------------------------------------------  
  34. ; Interrupt vector segment                                                      
  35. ;-----------------------------------------------------------------------------  
  36.  
  37. ABS0        segment use16 at 0                                                      
  38.                                         
  39.         org     6*4                                                                 
  40.  
  41. Orig_INT6       dd      ?                                                       
  42.                                                                                 
  43. ABS0        ends                                                                    
  44.                                         
  45.                                         
  46. ;-----------------------------------------------------------------------------  
  47. ; 80486 instruction macro -- because MASM 5.1 doesn't support the 80486!        
  48. ;-----------------------------------------------------------------------------  
  49.  
  50. XADD    macro                                                                   
  51.         db      0fh,0C0h,0D2h           ; 80486 instruction macro               
  52. ENDM                                                                            
  53.                                                                                 
  54.                                                                                 
  55. stdlib        segment    para use16 public 'slcode'                                     
  56.         assume  cs:cseg                                                         
  57.                                         
  58. sl_CPU_Type     proc    near
  59.         push    bx
  60.         push    cx
  61.         push    dx
  62. ;
  63. ;-----------------------------------------------------------------------------  
  64. ; Determine the CPU type by testing for differences in the CPU in the system.   
  65. ;-----------------------------------------------------------------------------  
  66. ; To test for the 8086/8088, test the value of SP after it is placed on the     
  67. ; stack.  The 8086/8088 increments this value before pushing it on the stack,   
  68. ; all other CPU's increment SP after pushing it on the stack.                   
  69. ;-----------------------------------------------------------------------------  
  70.         xor     ax,ax           ; clear CPU type return register        
  71.         push    sp              ; save SP on stack to look at           
  72.         pop     bx              ; get SP saved on stack                 
  73.         cmp     bx,sp           ; if 8086/8088, these values will differ
  74.         jnz     CPU_8086_exit   ; yep                                   
  75. ;-----------------------------------------------------------------------------  
  76. ; When we get here, we know that we aren't a 8086/8088.  And since all          
  77. ; subsequent processors will trap invalid opcodes via INT6, we will determine   
  78. ; which CPU we are by trapping an invalid opcode.                               
  79. ;   We are an 80486 if:  XADD   DX,DX   executes correctly                      
  80. ;             80386 if:  MOV    EDX,CR0 executes correctly                      
  81. ;             80286 if:  SMSW   DX      executes correctly                      
  82. ;             80186 if:  SHL    DX,5    executes correctly                      
  83. ;-----------------------------------------------------------------------------  
  84. ; Setup INT6 handler                                                            
  85. ;-----------------------------------------------------------------------------  
  86.  
  87.         enter   4,0                     ; create stack frame                    
  88.         mov     word ptr INT6, offset INT6_handler                               
  89.         mov     INT6+2,cs                                                       
  90.         call    set_INT6_vector         ; set pointer to our INT6 handler       
  91.         mov     ax,4                    ; initialize CPU flag=4 (80486)         
  92.         xor     cx,cx                   ; initialize semaphore                  
  93.                                         
  94. ;-----------------------------------------------------------------------------  
  95. ; Now, try and determine which CPU we are by executing invalid opcodes.         
  96. ; The instructions I chose to invoke invalid opcodes, are themselves rather     
  97. ; benign.  In each case, the chosen instruction modifies the DX register,       
  98. ; and nothing else.  No system parameters are changed, e.g. protected mode,     
  99. ; or other CPU dependant features.                                              
  100. ;-----------------------------------------------------------------------------  
  101. ; The 80486 instruction 'XADD' xchanges the registers, then adds them.          
  102. ; The exact syntax for a '486 compiler would be:  XADD  DX,DX.                  
  103. ;-----------------------------------------------------------------------------  
  104.  
  105.         XADD   ;DX,DX                   ; 80486                                 
  106.         jcxz    CPU_exit                                                        
  107.         dec     ax                      ; set 80386 semaphore                   
  108.         inc     cx                      ; CX=0                                  
  109.                                         
  110. ;-----------------------------------------------------------------------------  
  111. ; For a description on the effects of the following instructions, look in       
  112. ; the Intel Programmers Reference Manual's for the 80186, 80286, or 80386.      
  113. ;-----------------------------------------------------------------------------  
  114.         mov     edx,cr0                 ; 80386                                 
  115.         jcxz    CPU_exit                                                        
  116.         dec     ax                      ; set 80286 semaphore                   
  117.         inc     cx                      ; CX=0                                  
  118.                                     
  119.         smsw    dx                      ; 80286                                 
  120.         jcxz    CPU_exit                                                        
  121.         dec     ax                      ; set 80186 semaphore                   
  122.         inc     cx                      ; CX=0                                  
  123.                                         
  124.         shl     dx,5                    ; 80186/80188                           
  125.         jcxz    CPU_exit                                                        
  126.         dec     ax                      ; set UNKNOWN_CPU semaphore             
  127.                                         
  128. CPU_exit:                                                                       
  129.         call    set_INT6_vector                                                 
  130.         leave                                                                   
  131.                                                                                 
  132. CPU_8086_exit:  pop    dx
  133.         pop    cx
  134.         pop    bx                                                                
  135.         ret                                                                     
  136.                                                                                 
  137.                                                                                 
  138. ;-----------------------------------------------------------------------------  
  139. ; Set the INT6 vector by exchanging it with the one currently on the stack.     
  140. ;-----------------------------------------------------------------------------  
  141.  
  142. set_INT6_vector:                                                                
  143.         push    ds                                                              
  144.         push    ABS0                    ; save interrupt vector segment         
  145.         pop     ds                      ; make DS=INT vector segment            
  146.         mov     dx,word ptr ds:Orig_INT6;       ; get offset if INT6 handler    
  147.         xchg    INT6,dx                 ; set new INT6 offset                   
  148.         mov     word ptr ds:Orig_INT6,dx                                        
  149.         mov     dx,word ptr ds:Orig_INT6+2      ; get segment of INT6 handler   
  150.         xchg    INT6+2,dx               ; set new INT6 segment                  
  151.         mov     word ptr ds:Orig_INT6+2,dx                                      
  152.         pop     ds                      ; restore segment register              
  153.         ret                             ; split                                 
  154.                                                                                 
  155.                                                                                 
  156. ;-----------------------------------------------------------------------------  
  157. ; INT6 handler sets a semaphore (CX=FFFF) and adjusts the return address to     
  158. ; point past the invalid opcode.                                                
  159. ;-----------------------------------------------------------------------------  
  160.  
  161. INT6_handler:                                                                   
  162.         enter   0,0                     ; create new stack frame                
  163.         dec     cx                      ; make CX=FFFF                          
  164.         add     word ptr ss:[bp][2],3   ; point past invalid opcode             
  165.         leave                                                                   
  166.         iret
  167. ;
  168. ;                                                                            
  169. CPU_Type        endp                                                            
  170. cseg        ends                                                                    
  171.         end                                                                     
  172.