is there any way to check whether it's an 8086 or an 8088 in asm?
The same question for 186 & 188 !
I got Ralf Brown's int-list, but there's seems to be no way to detect which
processor is inside.
To tell the difference between an 8086/8088 and 80186/80188 you can
take advantage of the fact that the 8088 and 80188 have an 8 bit data
bus, whereas the other two have a 16 bit data bus. Therefore, you
could make a test that uses self-modifying code. Put the self modifying
code in a sensitive area so that on an 8088 the code would be modified,
but on an 8086 it wouldn't be modified because it would already be in
the cache.
To tell the difference between an 8086 and 80186 you can take advantage
of the fact that an 80186/80188 masks the shift count in the shift
instructions(with 00011111b), while an 8086/8088 doesn't.
Dave
--
For the world's funniest free jokes come to
http://www.twistedhumor.com/cgi-bin/affiliate/banner.cgi?1498
The DS-OS Operating System Programming page: http://dsos.cjb.net
Here you'll also find the source to a PS/2 mouse driver.
>is there any way to check whether it's an 8086 or an 8088 in asm?
Yes.
;
; Call this routine from your main code. Return is in AX, as follows:
;
; N = Not an 8086, 8088 or NEC chip.
; V = Processor is an NEC V20 or V30.
; 0 = Processor is an 8088.
; 1 = Processor is an 8086.
;
; First, let's check to see if we have a processor in the 8086/8088/V20
; family.
;
check_for_88:
pushf ;push original flags
pop ax ;get original flags in AX
mov cx,ax ;save original flags
and ax,0FFFh ;clear bits 12-15 in flags
push ax ;save new flags value on stack
popf ;replace current flags value
pushf ;get new flags
pop ax ;store new flags in AX
and ax,0F000h ;if bits 12-15 are set, then CPU
cmp ax,0F000h ; is an 8086/8088
je check_for_nec ;yes, we have an 8086, 8088 or V20
mov ax,'N' ;no, we don't have such a chip
ret ;return to caller
;
; The NEC V20/V30 are very compatible with the Intel 8086/8088.
; The only point of "incompatibility" is that they do not contain
; a bug found in the Intel CPU's. Specifically, the NEC CPU's
; correctly restart an interrupted multi-prefix string instruction
; at the start of the instruction. The Intel CPU's incorrectly
; restart in the middle of the instruction. This routine tests
; for that situation by executing such an instruction for a
; sufficiently long period of time for a timer interrupt to occur.
; If at the end of the instruction, CX is zero, it must be an NEC
; CPU; if not, it's an Intel CPU.
;
; Note that we're counting on the timer interrupt to do its thing
; every 18.2 times per second.
;
; Here's a worst case analysis: An Intel 8088/8086 executes 65535
; iterations of LODSB ES[SI] in 2+9+13*65535 = 851,966 clock ticks.
; If the Intel 8088/8086 is running at 10 MHz, each clock tick is
; 100 nanoseconds, hence the entire operation takes 85 milliseconds.
; If the timer is running at normal speed, it interrupts the CPU every
; 55ms and so should interrupt the repeated string instruction at least
; once.
;
check_for_nec:
MOV CX,0FFFFH ; Move a lot of data
STI ; Ensure timer enabled
;
; execute multi-prefix instruction. note that the value of ES as
; well as the direction flag setting is irrelevant.
;
PUSH AX ; Save registers
PUSH SI ;
REP LOCK LODSB ; Check for 8088 multi-prefix int problem
POP SI ; Restore
POP AX ;
cmp cx,0 ; if CX is zero, we have an NEC processor
jne check_for_8086 ; if not, go check for 8086
mov ax,'V' ; indicate V20/V30 in AX
ret ; return to caller
;
; Now let's check to see if we have an 8086. This code takes advantage of
; the 8088's 4-byte prefetch queues and 8086's 6-byte prefetch queues.
; By self-modifying the code at a location exactly 5 bytes away from IP,
; and determining if the modification took effect, we can differentiate
; between 8088s and 8086s.
;
check_for_8086:
mov ax,cs ; es == code segment
mov es,ax
std ; Cause stosb to count backwards
mov dx,1 ; dx is flag and we'll start at 1
mov di,OFFSET EndLabel ; di==offset of code tail to modify
mov al,090h ; al==nop instruction opcode
mov cx,3 ; Set for 3 repetitions
rep stosb ; Store the bytes
cld ; Clear the direction flag
nop ; Three nops in a row
nop ; provide dummy instructions
nop ;
dec dx ; Decrement flag (only with 8088)
nop ; dummy instruction--6 bytes
nop
EndLabel:
nop
mov ax,dx ; Store the flag in ax
ret ; return to caller
>To tell the difference between an 8086 and 80186 you can take advantage
>of the fact that an 80186/80188 masks the shift count in the shift
>instructions(with 00011111b), while an 8086/8088 doesn't.
This was documented in the int-list, also Intel gave me that code.
Thanx for nothing, but thanx,
Angelus
My program has to detect nearly every compatible CPU.
(also Sony NEC, Amstrad 80C8x, Cyrix, TI and AMDs)
So I need following codes to determine:
It's an 808x, so is it an 8086 or an 8088? (Done by your code)
It's an 808x, so is it an original 808x or an 80C8x CMOS version? (Need
code)
It's an 8018x, so is it an 80186 or an 80188? (Need code)
It's an 80486 with FPU, so is it an 80486DX or just a 487SX FPU? (Need code)
It's a Sony NEC, so is it a V20,V30,V40 or V50? (Need code)
Thanx for your code,
Angelus
TestQueue proc uses ax
mov bx, 1
mov al, TestInst ;Load opcode for INC BX (43h)
xor al, 8 ;Change (43h) to (4Bh) DEC BX
mov TestInst, al ;Move it back to proper place
nop ;If using 8-bit data bus,
nop ; these 4 NOP's will fill the
nop ; queue, allowing the next byte
nop ; to be changed.
TestInst db 43h ;This is opcode for INC BX
ret
TestQueue endp
BX has the result such that if
BX = 0, the CPU has an 8-bit data bus,
BX = 2, the CPU has a 16-bit data bus.
Wyatt also cleverly sutracts this value from 88 yielding 88 or 86, the
CPU type.
For NPX, the numeric coprocessor, you want to write your code to check
NPX status information without checking for errors which crashes the
diagnostics you're running. Try using FNINIT and FNSTSW instructions to
overwrite some predetermined memory location then check that location
for alteration. Note: FNINIT initializes the NPX without error checks
whereas FINIT does check for errors! Similarly for FNSTSW and FSTSW.
Hope that helps get you going.
--chris
Oh, this works for 186/188 too? Thanx.
>For NPX, the numeric coprocessor, you want to write your code to check
>NPX status information without checking for errors which crashes the
>diagnostics you're running. Try using FNINIT and FNSTSW instructions to
>overwrite some predetermined memory location then check that location
>for alteration. Note: FNINIT initializes the NPX without error checks
>whereas FINIT does check for errors! Similarly for FNSTSW and FSTSW.
>Hope that helps get you going.
That's the way my prog is detecting FPUs this way, but this feature is not
useable to seperate 486DX and i487SX from each other.