🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.os.msdos.programmer
Article #1884

Re: Detecting an 80486

#1884
From: Sidney Markowitz
Date: Wed, 15 Aug 1990 07:46
125 lines
5295 bytes
In article <1990Aug14.025550.17669@esegue.segue.boston.ma.us> johnl@esegue.segue.boston.ma.us (John R. Levine) writes:
>In article <3817@altos86.Altos.COM> rcollins@altos86.UUCP (Robert Collins) writes:
>>In some article, it was written:
>>+}  In my Infoplus program, the 286/386/486 are detected by trapping the
>>+}invalid opcode interrupt, and then trying instructions. 
>>[but there are lots of places where this doesn't work very well, either
>>because someone else gets the trap, or because some putatively unused opcodes
>>do secret things.]
>
>The Intel 486 Programmer's manual has sample code to tell the difference
>among the 8086, 286, 386, and 486 without any trapping at all.

;; Program to distinguish between 8086/80286/80386/80486
;; It does not trap illegal opcodes, and so works under virtual 8086
;; systems such as QEMM which cause other methods to crash.
;;
;; Notes: 1) It is possible for a monitor program that is handling a virtual
;; 8086 on an 80386 or 80486 to trap the instructions that access the
;; flags registers and make this code not work. But that would be a lot
;; of work to no purpose, so don't expect a problem in real life systems.
;; 2) This was only tested on an 80386 and an 80486. However, the code
;;   for 8086 and 80286 comes from an Intel manual and looks simple
;;
;; Acknowledgements:
;; This program gets its output code from a PC Magazine program that uses
;;   invalid opcode trapping and doesn't work under QEMM
;; The code to distinguish 8086 fro 80286 from 80386/486 is adapted from
;;   page 22-2 of the Untel 80486 Programmers Manual
;; The code to distiguish between 80386 and 80486 is adapted from pg 3-23
;;   of the same manual. Note that the comments in the manual describe
;;   the return value backwards.
;; The comments are my own
;;
;; Sidney Markowitz <sidney@saturn.ucsc.edu> or <sidney@ai.mit.edu>
 
        .MODEL  TINY
 
DOS     equ     21H
DosPrint equ    09H
DosExit equ     4CH
 
        .DATA
CPUMSG  DB      0DH,0AH,'CPU is an 80$'
I86     DB      '86$'
I286    DB      '286$'
I386    DB      '386$'
I486    DB      '486$'
CRLF    DB      0DH,0AH,'$'
 
        .CODE
        ORG     100H
        .386p   ;; allow 386 style assembler instructions
prog:
        mov     ah,DosPrint
        mov     dx,offset CPUMSG
        int     DOS
 
;; Test for 8086 by trying to set flags high nibble to 0
;; On an 8086, the nibble will remain all ones
        mov     dx,offset I86
        pushf
        pop     bx
        and     bh,0Fh
        push    bx
        popf
        pushf
        pop     ax
        and     ah,0F0h
        cmp     ah,0F0h
        je      TELLCPU    ; print out that this is an 8086
 
;; Test for 80286 by trying to set flags high nibble to all ones.
;; On an 80286, the nibble will remain all zeroes
        mov     dx,offset I286
        or      bh,0F0h
        push    bx
        popf
        pushf
        pop     ax
        test    ah,0F0h
        jz      TELLCPU
 
;; Distinguish an 80386 from an 80486
;; Bit 18 (40000H) of EFLAGS register is used only in the 486
;; This code flips it and tests if anything happened.
;;
;;
        mov     edx,esp      ; Save stack pointer
        and     esp,not 3    ; Align stack pointer to prevent a fault
                             ;  when we set the AC flag on a 486
        pushfd               ; Copy the EFLAGS register
        pop     eax          ;   into register eax
        mov     ecx,eax      ; Save the original EFLAGS value
        xor     eax,40000H   ; Flip the AC flag bit
        push     eax         ; Try to put the modified value back
        popfd                ;   into the EFLAGS register
        pushfd               ; Copy the EFLAGS register again
        pop     eax          ;   into eax
        xor     eax,ecx      ; Compare the old and new AC bits
        shr     eax,18       ; Shift and mask to get the AC comparison bit
        and     eax,1        ;   in the low order position of eax
        push    ecx
        popfd                ; Restore EFLAGS that were saved on entry
        mov     esp,edx      ; And restore stack pointer to saved value
;;
;; at this point ax = 0 on a 386
;;               ax = 1 on a 486
        mov     dx,offset I386
        test    ax,ax
        jz      TELLCPU
        mov     dx,offset I486
 
;; output a message with the result, then exit
 
TELLCPU:
        mov     ah,DosPrint
        int     DOS
        mov     ah,DosPrint
        mov     dx,offset CRLF
        int     DOS
        mov     al,0
        mov     ah,DosExit
        int     DOS
        end     prog
;;;; end of program ;;;;;;;;
Technical Details
Message-ID: <6020@darkstar.ucsc.edu>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!cs.utexas.edu!usc!apple!agate!darkstar!saturn.ucsc.edu!sidney
References: <26a858b9@ralf> <3817@altos86.Altos.COM> <1990Aug14.025550.17669@esegue.segue.boston.ma.us>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!cs.utexas.edu!usc!apple!agate!darkstar!saturn.ucsc.edu!sidney
From: sidney@saturn.ucsc.edu (Sidney Markowitz )
Newsgroups: comp.os.msdos.programmer
Subject: Re: Detecting an 80486
Summary: Here's code that does it without trapping
Message-ID: <6020@darkstar.ucsc.edu>
Date: 15 Aug 90 07:46:47 GMT
References: <26a858b9@ralf> <3817@altos86.Altos.COM> <1990Aug14.025550.17669@esegue.segue.boston.ma.us>
Sender: usenet@darkstar.ucsc.edu
Organization: University of California, Santa Cruz
Lines: 125