[comp.sys.ibm.pc] How to tell the difference between 80386 virtual 8086 mode and 286 real mode?

brad@looking.UUCP (Brad Templeton) (07/27/88)

Does anybody have any info on this?  Please respond by mail.
I know you can spot a 386 in real mode by trying to set the IOPL bits in
the flag word, but this doesn't work in virtual 8086 mode.

In general, any test should not involve triggering a trap.  There
are obviously lots of tests to try that would trap on one machine and
not on the other.
-- 
Brad Templeton, Looking Glass Software Ltd.  --  Waterloo, Ontario 519/884-7473

danno@microsoft.UUCP (Daniel A. Norton) (07/29/88)

In article <1873@looking.UUCP>, brad@looking.UUCP (Brad Templeton) writes:
> Does anybody have any info on this?  Please respond by mail.
> I know you can spot a 386 in real mode by trying to set the IOPL bits in
> the flag word, but this doesn't work in virtual 8086 mode.

I sent you mail on this, but I've since been told of a better method.
The best way is to use the SMSW instruction.  It is non-privileged (as
opposed to LMSW) so it works fine in Virtual 8086 mode.  This instruction
stores some flags into a 16-bit operand.  The low bit indicates whether
or not the system is in protect mode.  A 286 in real-mode has a zero in
this bit.  An 80386 in V86 mode (presumably also in protect mode) has
a one in this bit.  I'm not sure that it makes sense to have the V86
mode set while in real-mode, so this should be safe.

Example:
	SMSW	AX
	RCR	AX,1
	JC	V86Mode
R286Mode:
	.
	.
	.
V86Mode:

This presumes, of course, that you know that you're not executing on
an 8088, because SMSW is illegal on that chip.
-- 
Any opinions expressed are mine, not my employer's.
nortond@microsof.beaver.washington.EDU nortond%microsof@uw-beaver.ARPA
{decvax,decwrl,sco,sun,trsvax,uunet,uw-beaver}!microsof!nortond

brad@looking.UUCP (Brad Templeton) (07/30/88)

> use SMSW

This does sound like a good method.  Another method, which I developed
on my own while waiting for replies, was to examine the length of the
instruction prefetch queue.   This can even tell the difference between
an 8088 and and 8086 if you want it to.  (8088 = 4, 8086,286 = 6, 386 = 8)

But that does sound like a rather scary way to do things, since Intel is
certainly free to change the length of this in future chips, or to put
in impure code checking into the prefetch hardware.

For those who want it,...

prefcount	PROC	NEAR
		; must preserve ax.  It does
		mov	bx,offset point
		mov	cx,0
		mov	dx,12		; max iter
	kloop:
		nop
		nop
		; store "inc cx" at one of the nops
		mov	byte ptr cs:[bx],41h		; inc cx
	point:
		; execute a chain of nops, one that might be the "inc cx"
		REPT	12
		nop
		ENDM
		; restore the "inc cx" back to a nop
		mov	byte ptr cs:[bx],90h		; nop
		; go on to the next byte
		inc	bx
		; check we haven't gone too far
		dec	dx
		jz	pcdone
		; keep looping until the inc was interpreted
		jcxz	kloop
	 pcdone:
		; we already have the index of the first non-prefetched
		; byte plus one (we incremented anyway).  Now we use
		; point-1 to add another to it because of the three byte
		; instruction at the front
		; the result is 6 for 286 and 8 for 386. (4 for 8088)
		sub	bx,offset point-1
		ret
prefcount	ENDP

-- 
Brad Templeton, Looking Glass Software Ltd.  --  Waterloo, Ontario 519/884-7473