Intel CPU ID code problem on Athlon

  • Thread starter Thread starter nutso fasst
  • Start date Start date
N

nutso fasst

I have a small program that initially clears the display and writes some
text to it, then it tests to determine what CPU it's running on. Later in
the program it hooks INT 08. The program ran OK on Athlon in real mode, but
when run in an NTVDM, the screen wasn't cleared and the initial message
never appeared--console was dead. From debug the program ran OK. If I
removed the code that checked for 386 and 486 it ran OK. And if I didn't
hook INT 08 it ran to completion without crashing.

I found a workaround. Modified CPU check code follows. Note the two STI
instructions. Both were required. If anyone has any ideas why, please
hare. --nf

; check for 386
pushfd
pop eax ; eflags in eax
mov ecx, eax ; in ecx
xor eax, 40000h ; flip AC bit
push eax
popfd ; back on stack
pushfd
pop eax ; back in eax
xor eax, ecx ; can't toggle AC bit?
jz got_cpu_type ; processor=80386
inc cputype
push ecx
popfd ; restore AC bit in eflags
sti ; SET INTERRUPT FLAG
; check for 486
mov eax, ecx ; original eflags
xor eax, 200000h ; flip ID bit
push eax
popfd ; back in eflags
pushfd
pop eax ; back in eax
xor eax, ecx ; can't toggle ID bit?
jz got_cpu_type ; processor=80486
inc cputype ; processor=pentium or later
got_cpu_type:
sti ; SET INTERRUPT FLAG
 
nutso said:
I have a small program that initially clears the display and writes some
text to it, then it tests to determine what CPU it's running on. Later in
the program it hooks INT 08. The program ran OK on Athlon in real mode, but
when run in an NTVDM, the screen wasn't cleared and the initial message
never appeared--console was dead. From debug the program ran OK. If I
removed the code that checked for 386 and 486 it ran OK. And if I didn't
hook INT 08 it ran to completion without crashing.

I found a workaround. Modified CPU check code follows. Note the two STI
instructions. Both were required. If anyone has any ideas why, please
hare. --nf

I assume that you've set a CLI (clear interrupts) instruction earlier
in that program? Clearing the interrupts in a V86 window not on
disables external hardware interrupts, but it also disables software
interrupts. That's because the INT instructions that you so casually
make use of in a Real mode environment is a much more complex process
in a V86 mode window. In V86 mode, the software interrupt ends up
causing a context switch back to the protected mode kernel where the
interrupt is actually handled. The protected mode kernel figures out
that it's something coming from a v86 window and ends up manually
calling the routines directly in the V86 operating system. However, if
you've set the CLI instruction, it doesn't call any of the routines
inside the V86 operating system, it just ignores them. That's why you
had to reenable interrupts with the STI instruction again otherwise
your Int 08 routine would never get called.

Yousuf Khan
 
YKhan said:
I assume that you've set a CLI (clear interrupts) instruction earlier
in that program?

Thanks for the prompt response.

No, there is no CLI prior to the CPU test code.
... Clearing the interrupts in a V86 window not on
disables external hardware interrupts, but it also disables software
interrupts.

It does? Which ones? Int 21h and int 10h still work in V86 with interrupts
cleared. In any case, if interrupts were being disabled by a CLI then int 08
wouldn't fire and the program wouldn't function properly in real mode, but
it does. Nor would simply removing that bit of code solve the problem, but
it does.

The only functions prior to the CPU check are clearing the display (using
int 10h) and writing to the display (int 21h, ah=40h). The DOS window isn't
cleared prior to lockup, so I surmise the lockup is occurring after the
display buffer is updated but before the buffer is written to the display.
The cursor continues to blink.

Since posting my previous message I was able to reproduce the problem, in
spite of the STIs, by running the program within seconds of assembling it. I
then added a loop of HLT instructions after the CPU check. With that I have
not been able to repro the problem. Unless I remove the STIs, that is. Then
the problem returns. If it were just a matter of inserting byte-size
instructions, NOPs would do, but they don't. The evidence suggests some
quirk in the CPU when in V86 mode.

nf
 
nutso said:
I have a small program that initially clears the display and writes some
text to it, then it tests to determine what CPU it's running on. Later in
the program it hooks INT 08. The program ran OK on Athlon in real mode, but
when run in an NTVDM, the screen wasn't cleared and the initial message
never appeared--console was dead. From debug the program ran OK. If I
removed the code that checked for 386 and 486 it ran OK. And if I didn't
hook INT 08 it ran to completion without crashing.

I found a workaround. Modified CPU check code follows. Note the two STI
instructions. Both were required. If anyone has any ideas why, please
hare. --nf

I would also ask in comp.lang.asm.x86
 
nutso said:
Thanks for the prompt response.

No, there is no CLI prior to the CPU test code.
Interesting.



It does? Which ones? Int 21h and int 10h still work in V86 with interrupts
cleared. In any case, if interrupts were being disabled by a CLI then int 08
wouldn't fire and the program wouldn't function properly in real mode, but
it does. Nor would simply removing that bit of code solve the problem, but
it does.

Actually, now that these things are slowly starting to come back to me,
I'm remembering the purposes of these various interrupts. Int 08h is the
hardware timer tick interrupt, while its user-mode counterpart is Int
1Ch. Why are you hooking the timer interrupt anyways?
Since posting my previous message I was able to reproduce the problem, in
spite of the STIs, by running the program within seconds of assembling it. I
then added a loop of HLT instructions after the CPU check. With that I have
not been able to repro the problem. Unless I remove the STIs, that is. Then
the problem returns. If it were just a matter of inserting byte-size
instructions, NOPs would do, but they don't. The evidence suggests some
quirk in the CPU when in V86 mode.

Yes, the Int 08h would be handled entirely outside the V86 window, try
hooking the Int 1Ch instead.

Yousuf Khan
 
Yousuf Khan said:
Yes, the Int 08h would be handled entirely outside the V86 window, try
hooking the Int 1Ch instead.

Thanks, but I didn't ask for possible workarounds. I was curious to learn
why a PUSHFD/POPFD would require a followup STI in v86 mode. Forget the cpu
check eflags manipulations. All it takes is a single pushfd/popfd pair. The
program locks up unless those instructions are followed by sti. Why? What's
happening? Doesn't look like I'm going to find out.

regards, nf
 
Actually, it's just the POPFD instruction that does it. PUSHFD/POP EAX is
not a problem.
 
Grumble said:
I would also ask in comp.lang.asm.x86

Did that, thanks. With any instruction that can affect the IF (such as POPFD
and STI) being trapped by the VDM's v86 monitor (running in pmode), maybe
the problem has nothing to do with the CPU being Athlon.

nf
 
"nutso fasst":
...maybe the problem has nothing to do with the CPU being Athlon.

Celeron is the same. Impetuous assumption. Thanks again to those who
responded, and apologies for the bother.

nf
 
Back
Top