On 1999-10-08 Sebastian-Gottsch...@T-Online.de
said:
>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