home *** CD-ROM | disk | FTP | other *** search
- ; TASM 2.0 required
- quirks
- masm51
-
- code SEGMENT WORD PUBLIC 'CODE'
-
- ASSUME CS:code
- public GetProz,CoPro,DXorSX
-
- ;**********************************************************************;
- ;* P R O Z P A *;
- ;*--------------------------------------------------------------------*;
- ;* Aufgabe : Ermittelt den Typ von Prozessor, der in einem *;
- ;* PC installiert ist. *;
- ;* In dieser Version ist das Programm zur Um- *;
- ;* wandlung in INLINE-Befehle und damit zur Ein- *;
- ;* bindung in ein PASCAL-Programm vorgesehen. *;
- ;*--------------------------------------------------------------------*;
- ;* Autor : MICHAEL TISCHER *;
- ;* entwickelt am : 22.08.1988 *;
- ;* letztes Update : 22.08.1988 *;
- ;* *;
- ;* Modifiziert von Michael Holin (486,Pentium-Erkennung) *;
- ;* *;
- ;**********************************************************************;
-
- ;== Konstanten =========================================================
- p_pentium equ 9
- p_80486 equ 8
- p_80386 equ 7
- p_80386sx equ 7 ;Codes für die verschiedenen Pro-
- p_80286 equ 6 ;zessortypen
- p_80186 equ 5
- p_80188 equ 4
- p_v30 equ 3
- p_v20 equ 2
- p_8086 equ 1
- p_8088 equ 0
-
- ;fernen haben die Bits 5-7 folgende Bedeutung:
- ;
- ; 8 7 6 5 | 4 3 2 1
- ; Weitek-Coprozessor vorhanden ──────┘ │ │
- ; Coprozessor wird emuliert ───────────┘ │
- ; CPU ist im Virtual Mode ───────────────┘
-
- ;== Code ===============================================================
-
-
- getproz proc far ;diese Prozedur ist das eigentliche
- ;Hauptprogramm
- push bp
- mov bp,sp
- pushf ;den Inhalt des Flag-Registers sichern
- push cx ;den Inhalt aller veränderten Register
- push dx ;auf dem Stack sichern
- push di
- push si
- push es
- ;-- auf 80386/80286 testen -----------------------------------
-
- xor ax,ax ;AX auf 0 setzen
- push ax ;und auf den Stack bringen
- popf ;als Flag-Register vom Stack holen
- pushf ;wieder auf den Stack bringen
- pop ax ;und als AX zurückholen
- and ax,0f000h ;nur die oberen 4 Bits nicht löschen
- cmp ax,0f000h ;sind die Bits 12 - 15 alle gleich 1?
- je nicht_386 ;JA, kann kein 80386 oder 80286 sein
-
- ;-- testen, ob es sich um 80386 oder 80286 handelt -----------
-
- mov dl,p_80286 ;es handelt sich auf jeden Fall um
- mov ax,07000h ;einen der Beiden Prozessoren
- push ax ;den Wert 07000h auf den Stack bringen
- popf ;als Flag-Register zurückholen
- pushf ;und wieder auf den Stack bringen
- pop ax ;in das AX-Register zurückholen
- and ax,07000h ;nur die Bits 12 - 14 nicht ausblenden
- je pende ;sind die Bits 12 - 14 alle gleich 0?
- ;JA --> es handelt sich um einen 80286
-
- inc dl ;Nein, es handelt sich um einen 80386
- ;oder 80486
- .386p
- call is486 ;Test auf 486 und Pentium
- smsw bx
- test bl,4 ;Koprozessor-Emulation ?
- jz short @f
- or dl,32 ;JA, dann 32 draufaddieren
- @@: test bl,1 ;CPU in Virtual Mode ?
- jz short @f
- or dl,16 ;JA, dann 16 draufaddieren
- @@: xor eax,eax
- int 11h ;Weitek-Prozessor installiert?
- test eax,1000000h
- jz pende
- or dl,64 ;dann 64 draufaddieren
- ; jmp pende
-
-
-
- pende: ;die Testes sind abgeschlossen
-
- xor ax,ax
- mov al,dl ;Proz.Code in Return-Var. ablegen
- pop es ;die gesicherten Register wieder vom
- pop si ;Stack holen
- pop di
- pop dx
- pop cx
- popf ;Flag-Register wieder vom Stack holen
- jmp ende ;zurück zum Aufrufer
- ;-- auf 80186 bzw. 80188 testen ------------------------------
-
- nicht_386:
-
- mov dl,p_80188 ;Code für 80188 laden
- mov al,0ffh ;alle Bits im AL-Register auf 1 setzen
- mov cl,021h ;Anzahl der Shift-Operationen nach CL
- shr al,cl ;AL CL mal nach rechts verschieben
- jne short t88_86 ;AL ist nicht 0, es muß sich um den
- ;80188 oder 80186 handeln
-
- ;-- auf NEC V20 oder V30 testen ------------------------------
-
- mov dl,p_v20 ;Code für NEC V20 laden
- sti ;Interrupts sollen erlaubt sein
- mov si,0 ;mit dem ersten Byte in ES beginnen
- mov cx,0ffffh ;ein komplettes Segment lesen
- rep lods byte ptr es:[si] ;REP mit einem Segment-Override
- ;funktioniert nur bei NEC V20, V30
- or cx,cx ;wurde das komplette Segment gelesen?
- je t88_86 ;JA --> ist V20 oder V30
-
- mov dl,p_8088 ;NEIN --> muß 8088 oder 8086 sein
-
- ;-- auf ...88 oder ...86 bzw. V20 oder V30 testen ------------
-
- t88_86:
-
- push cs ;CS auf dem Stack merken
- pop es ;und als ES zurückholen
- std ;bei Stringbefehlen abwärts zählen
- mov al,0fbh ;Befehlscode für "STI"
- mov cx,3 ;den Stringbefehl 3 mal ausführen
- call get_di ;Startadresse DI holen
- t86_1: cli ;Interrupts unterdrücken
- rep stosb
- cld ;bei Stringbefehlen wieder aufwärts
- nop ;Dummy-Befehle zum Queue füllen
- nop
- nop
-
- inc dx ;Prozessorcode inkrementieren
- nop
- q_end: sti ;Interrupts wieder erlauben
- jmp pende
-
- ;-------------------------------------------------------------
-
-
- getproz endp ;Ende der PROG-Prozedur
-
- is486 proc ;-- Der folgende Test zwischen 80386 und 80486 beruht auf ----
- ;-- einer Erweiterung des EFlags-Registers beim 80486 in
- ;-- Bitposition 18.
- ;-- Dieses Flag gibt es beim 80386 nicht, und deshalb läßt
- ;-- sich sein Inhalt auch nicht per Software verändern.
-
- cli ;keine Interrupts jetzt
-
- mov ebx,esp ;aktuelles SP merken
- and esp,0FFFCh ;auf DWORD abrunden
- pushfd ;Flag-Register über
- pop eax ;Stack nach AX
- mov ecx,eax ;und in CX merken
- xor eax,1 shl 18 ;Alignment-Bit umdrehen
- push eax ;und in das Flag-
- popfd ;Register bringen
- pushfd ;Flag wieder auf Stack
- pop eax ;und dann nach AX
- push ecx ;alten Flag-Inhalt
- popfd ;wieder zurück
- xor eax,ecx ;AL-Bit testen
- shr eax,18 ;AL-Bit nach Bit 0
- and eax,1h ;alle anderen ausbl.
- mov esp,ebx ;SP wieder zurücks.
-
- add dl,al ;AL ist 1, wenn 486
-
-
- mov ebx,esp ;aktuelles SP merken
- and esp,0FFFCh ;auf DWORD abrunden
- pushfd ;Flag-Register über
- pop eax ;Stack nach AX
- mov ecx,eax ;und in CX merken
- xor eax,1 shl 21 ;ID-Bit umdrehen
- push eax ;und in das Flag-
- popfd ;Register bringen
- pushfd ;Flag wieder auf Stack
- pop eax ;und dann nach AX
- push ecx ;alten Flag-Inhalt
- popfd ;wieder zurück
- xor eax,ecx ;AL-Bit testen
- shr eax,21 ;AL-Bit nach Bit 0
- and eax,1h ;alle anderen ausbl.
- mov esp,ebx ;SP wieder zurücks.
-
- sti ;Interrupts wieder erlauben
- add dl,al ;AL ist 1, wenn Pentium
- ret
- is486 endp
-
- ;-- GET_DI ermittelt DI für 88/86-Test ---------------------------------
-
- get_di:
-
- pop di ;Rücksprungadresse vom Stack holen
- add di,9 ;9 Bytes davon entfernt anfangen
- jmp t86_1 ;wieder in die Testroutine springen
-
- ende:
- mov sp,bp
- pop bp
- ret
-
-
- .8086
-
- ;== Ende ===============================================================
-
-
- .386
- DXorSX proc far ;Mem-Access via DWord-Read
- assume cs:CODE, es:nothing
- push bp
- mov bp,sp
- push ds
- push es
- push si
- push di
- push cx
- pushf
- mov ax,0040h
- mov ds,ax
- mov bx,00F0h
- xor ecx,ecx
- xor esi,esi
- mov cx,word ptr ds:bx ;Anzahl
- mov si,word ptr ds:bx + 2 ;Offset
- mov ax,word ptr ds:bx + 4 ;Segment
- mov ds,ax
- cld
- cli
- mov al,34h
- out 43h,al
- jmp $+2
- mov al,0
- out 40h,al
- jmp $+2
- out 40h,al
- rep
- lodsd
-
- mov al,0
- out 43h,al
- sti
- jmp $+2
- in al,40h
- xchg ah,al
- jmp $+2
- in al,40h
- xchg ah,al
- neg ax ;return time for doing the loop
- popf
- pop cx
- pop di
- pop si
- pop es
- pop ds
- mov sp,bp
- pop bp
- ret
- DXorSX endp
-
-
- .8086
- ; calling convention:
- ;
- ; function CoPro:word;
- ;
- ; returns:
- ;
- ; tucked away neatly in your AX....
- ;
- ; 0 if NO NDP is found
- ; 1 if an 8087
- ; 2 if an 80287
- ; 3 if an 80387
- ;
- ; NOTE:
- ;
- ; There are lotsa ways of handling the way this function returns
- ; it's data. For my purposes, I have elected this one because
- ; it requires only int arithmetic on the caller's end to extract
- ; all the info I need from the return value. I think that I'm
- ; well enough 'commented' in the following code so that you will
- ; be able to tinker and Putz until you find the best return tech-
- ; nique for Ur purposes without having to reinvent the wheel.
- ;
- ; REFERENCES:
- ;
- ; ndp_type is adopted from Ted Forgeron's article in PC
- ; Tech Journal, Aug '87 p43.
- ;
- ; In the event of subsequent republication of this function,
- ; please carry forward reference to these two gentlemen as
- ; original authors.
- ;
- ; Copr. 1987 Pat Shea - Psi! (that Copr. is on there cuz my
- ; lawyer sez I should, but feel
- ; free to hack away!!! pats.)
- ;
- ; Update: 1/1/88 - changed this code slightly so that it is
- ; compilable using MASM 5.0, and the test.c
- ; file using MSC 5.0. <Albert Stein>
- ;
-
- CoPro proc far
- assume cs:CODE, es:nothing
- push BP ; save where Ur at
- mov BP,SP ; going in.....
-
- push DI
- push SI
- push CX ; not really needed for MSC but kinda
- ; nice to do cuz someone else might
- ; want to use the function and we do
- ; use CX later on
-
- call ndp_type ; check for math coprocessor (NDP) type
- ; and hold that result in AX
-
- pop CX ; put things back the way that you
- pop SI ; found 'em when you started this
- pop DI ; little drill off.....
- pop BP
- ; AND
- ret ; go back to where you came from....
- ; ( ===> the calling program )
- ; with Ur results sittin' in AX !!
- even
- control dw 0 ; control word needed for the NDP test
-
- CoPro endp
-
-
- ; Check for an NDP.
- ;
-
- ndp_type PROC
-
- do_we: fninit ; try to initialize the NDP
- mov byte ptr control+1,0 ; clear memory byte
- fnstcw control ; put control word in memory
- mov AH,byte ptr control+1 ; iff AH is 03h, you got
- cmp AH,03h ; an NDP on board !!
- je chk_87 ; found somethin', keep goin'
- xor AX,AX ; clean out AX to show a zero
- jmp SHORT NDPbye ; return (i.e., no NDP)
-
- ; 'got an 8087 ??
-
- chk_87: and control,NOT 0080h ; turn ON interrupts (IEM = 0)
- fldcw control ; load control word
- fdisi ; turn OFF interrupts (IEM = 1)
- fstcw control ; store control word
- test control,0080h ; iff IEM=1, 8087
- jz chk287 ; 'guess not! March on....
- mov Ax,1 ; set up for a 1 return to
- jmp SHORT NDPbye ; show an 8087 is on board
- ; if not.... would you believe an 80287 maybe ??
- .286
- CHK287: finit ; set default infinity mode
- fld1 ; make infinity
- fldz ; by dividing
- fdiv ; 1 by zero !!
- fld st ; now make a
- fchs ; negative infinity
- fcompp ; compare Ur two infinities
- fstsw control ; iff, for 8087 or 80287
- fwait ; sit tight 'til status word is put away
- mov AX,control ; getchur control word
- sahf ; putchur AH into flags
- jnz got387 ; NO GOOD.... march on !!
- mov Ax,2 ; gotta be a 80287 cuz we already tested
- jmp SHORT NDPbye ; for an 8087
-
- ; We KNOW that there is an NDP on board otherwise we would have bailed
- ; out after 'do_we'. It isn't an 8087 or an 80287 or we wouldn't have
- ; gotten this far. It's gotta be an 80387 !!
- got387: mov ax,3 ; call it an 80387 and return 3
- NDPbye: ret ; and go back where you came from
- ; (i.e., ===> _chips) carrying the NDP
- ; type in Ur DL register
- ndp_type endp
-
- code ends
- end
-