home *** CD-ROM | disk | FTP | other *** search
-
- ;; 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 ;;;;;;;;
-
-
-