Yes. IIRC the 8086 & 8088 have different sized prefetch queues
(6 vs 4 bytes) and you can distinguish by some simple self-mod code
-- Robert
>I know 8088 is the only processor in x86 family
>where SP is modified BEFORE pushing.
>But is it the same for 8086 ?
Yes, the 8088 and 8086 share the same core.
>If yes, is it possible to distinct 8088 and 8086
>by software ?
Yes, using the fact that the 8086 has a slightly larger
instruction prefetch queue. By changing an instruction
about 5 bytes ahead, only the 8088 will execute
the changed instruction as the 8086 already has
loaded the original instruction.
There should be source code of old CPU ID programs
which will do this and a lot more.
H
ASFAIK this behaviour of PUSH SP was changed first with the
80186/80188 series, thus the 8086 should show it as well.
V20/V30 have the same behaviour as 8088/8086, but they show a
different behaviour regarding string instructions: A bug which caused
stuff like
rep lodsb es:[si]
to terminate during an interrupt was fixed in the V20/V30 versions
of the 8088/8086
>Yes. IIRC the 8086 & 8088 have different sized prefetch queues
>(6 vs 4 bytes) and you can distinguish by some simple self-mod code
That愀 right. This works because 8086/8088 do not have SMC testing
capabilities like newer CPUs usually do.
On Mon, 24 Jun 2002 15:56:03 +0000 (UTC), Pierre Maurette spake thus:
Here's the code I posted about 6 months ago to distinguish between the
8086, 8088, NEC V20/V30, 80186 and 80188;
mov ax,1
mov cx,32
shl ax,cl ; 80186 will AND cl with 31.
jnz x186
pusha ; on 808x this will be a 2-byte nop
stc ; stc will only execute on NECs
jc nec
mov ax,cs
add ax,01000h
mov es,ax ; target for movsb
xor si,si
mov di,100h
mov cx,08000h
rep es movsb ; on 80C8x, interrupted rep will
or cx,cx ; resume, on NMOS it won't
jz cmos
nmos:
mov ax,0
jmp x8_16
cmos:
mov ax,2
jmp x8_16
nec:
mov ax,4
jmp x8_16
x186:
push sp ; 286+ will push the old value
pop ax
cmp ax,sp
jz x286
mov ax,6
x8_16:
xor bx,bx
mov byte [a1],043h ; change nop to "inc bx"
a1 nop ; on x88, this is inc bx
or bx,bx ; it is nop on x86
jnz .1 ; jump if it's an x88
or bx,1 ; bit 0 = x86
.1
jmp cpuid_end
x286:
pushf
pop ax
or ah,070h
push ax
popf
pushf
pop ax
and ax,07000h
jnz x386
mov ax,8
jmp cpuid_end
x386:
mov ax,0Ah
cpuid_end:
This code assembles under nasm as 105 bytes of machine code, and will
return the following values in ax:
AX CPU
0 8088 (NMOS)
1 8086 (NMOS)
2 8088 (CMOS)
3 8086 (CMOS)
4 NEC V20
5 NEC V30
6 80188
7 80186
8 286
0Ah 386 and higher
I haven't tested it, as I have nothing older than a 386 (yet), but I
believe it is all correct.
--
Debs
<debs> at <dwiles> <.> <demon> <.> <co> <.> <uk>
http://debs.future.easyspace.com/
----
I started out with nothing, and I still have most of it.
On Mon, 24 Jun 2002 21:55:59 +0000 (UTC), TS spake thus:
>>: I know 8088 is the only processor in x86 family
>>: where SP is modified BEFORE pushing.
>>: But is it the same for 8086 ?
>
>ASFAIK this behaviour of PUSH SP was changed first with the
>80186/80188 series, thus the 8086 should show it as well.
The behaviour of PUSH SP was changed from the 286, the 8018x has the
same behaviour as the 808x.
Another option is to use the flags. On the 808xand 8018x, bits 12-15
of eflags are always set. On the 286, bits 12-15 are always clear in
real mode. On the 386, in real mode, bit 15 is always clear and bits
12-14 contain the last value loaded into them (meaning that they can
be flipped).
Thus, the following sequence will work:
pushf ; save flags
push word -1
popf
pushf
pop ax
popf ; restore flags
test ax,0F000h
jz .80286
test ax,08000h
jnz .386
.8086
; here if it is an 808x, NEC or 18x
.80286
; here if it is a 286
.386
; here if it is a 386+
That is an alternative to the code I posted earlier. I use that
succesfully in my code to detect 386+ processors.
>>Yes. IIRC the 8086 & 8088 have different sized prefetch queues
>>(6 vs 4 bytes) and you can distinguish by some simple self-mod code
>
>That愀 right. This works because 8086/8088 do not have SMC testing
>capabilities like newer CPUs usually do.
It turns out that this also works on the 186/188, which makes
detection a synch :)
I've seen that data posted a few places, but have not yet been able to
test on anything pre-386. I should be able to test on a 286 later in
the week, but I have no idea when/if I'll get to test on 808x or 18x
systems. The 286 systems I'm getting are part of a job lot of 50 PC
systems I'm buying, otherwise I'd not even consider buying them :) May
as well test my detection code on them before selling them on...
You will also find that pusha executes as "jmp $+2" on an 808x, but
works on the NEC chips and the 186+. Also the NEC and 808x don't mask
the shift value so you can set a register and shift by 32 to test for
a 186+, while it will clear the register on an NEC or an 808x. The
code I posted before uses a combination of these tests (plus the SMC
test for 8-bit vs 16-bit).
On Mon, 24 Jun 2002 21:56:05 +0000 (UTC), Debs spake thus:
> pusha ; on 808x this will be a 2-byte nop
> stc ; stc will only execute on NECs
> jc nec
>
<snip>
>nec:
; there should have been:
popa ; clean up the stack :)
> mov ax,4
> jmp x8_16
>x186:
--
The 8088 and 8086 have exactly the same behavior on ALL instructions,
including push SP. The only difference is timing.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
This is correct, except that the needed code isn't that obvious. :-)
Here's a snippet from my old cputype.asm code:
Terje
--
- <Terje.M...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"
ALIGN_COUNT = 0
MAX_PREFETCH = 99 ; Should be OK for 586+?
get_prefetch proc near
; This code can either overwrite the prefetch queue from the front or
from
; the back, the following IF determines which will be used.
IF 1
std ; Overwrite from the back
mov di,offset last_opcode
ELSE
cld ; Overwrite from the
front
mov di,offset first_opcode
ENDIF
mov cx,MAX_PREFETCH
push cx
push di
mov al,41h ; INC CX opcode
rep stosb ; Restore code if multiple
pop di ; calls to this subroutine!
pop cx
mov ax,0FBh ; == STI opcode
ALIGN 16 ; PARA alignment for 486+!
IF ALIGN_COUNT
REPT ALIGN_COUNT
NOP
ENDM
ENDIF
; The following block of code, from DoTest to first_opcode, is exactly
; 16 bytes long, so first_opcode will have the same alignment as DoTest.
DoTest:
mov bx,1234h ; dummy value for MUL/DIV
jmp short $+2 ; Flush prefetch queue
; in case multiple
calls.
cli ; No IRQs to mix up the result
mul bx
div bx ; MUl/DIV pairs are short and
mul bx ; slow opcodes, to fill the
div bx ; prefetch queue totally!
rep stosb ; Will try to overwrite code
; already in the
prefetch q.,
first_opcode label byte
REPT MAX_PREFETCH - 1 ; starting from the end.
inc cx
ENDM
last_opcode label byte
inc cx
sti
cld
mov ax,cx
ret
get_prefetch endp
I've used this code for that purpose:
* * *
;Test 8088/8086 based upon prefetch queue length. 8088 = 4-byte, 8086
= 6-byte.
;Code modified from Szilagyi, EDN Design Ideas, Apr 26, 1990, pg 232.
CLI
MOV BH,8 ;Assume 8088
MOV SI,OFFSET QUE_CODE + 1 ;Target code ahead of or in queue
JMP SHORT $+2 ;Reset que (important!)
MOV [SI],BH ;2 bytes. Modify targ if 8088,not
;if 8086
NOP ;1 byte
NOP ;1 byte - end of 8088 queue
QUE_CODE:
MOV BH,6 ;6 is outside 8088 queue, just
;inside 8086
STI
JMP SHORT GOT_CPU
Bob Masta
tech(AT)daqarta(DOT)com
D A Q A R T A
Data AcQuisition And Real-Time Analysis
Shareware from Interstellar Research
www.daqarta.com
ftp://ftp.sudleyplace.com/sudleyplace/cpuid.zip
This type of program could well be the most often reinvented wheel in
the assembler programming community. Perhaps everyone thinks of it
as a really good way to learn assembler programming.
_________________________________________
Bob Smith -- bsm...@sudleydeplacespam.com
a.k.a. bsm...@qualitasdespam.com
I've been getting a lot of junk e-mail lately,
so to reply to me directly, delete "despam".