I need someone with an old timer to test this CPUID tester.

Started by hutch--, April 24, 2010, 12:29:19 PM

Previous topic - Next topic

hutch--

Sorry to wear a few people out but I have no way of testing this function as I don't own anything old enough to not have CPUID present. I extracted the method out of a locked PDF intel manual and may have botched something.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    is_cpuid PROTO

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    xor eax, eax

    invoke is_cpuid

    .if eax == 1
      print "CPUID Supported",13,10
    .else
      print "CPUID not supported",13,10
    .endif

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

is_cpuid proc

    pushfd
    pop eax

    mov ecx, eax
    xor eax, 00000000001000000000000000000000b          ; set bit 21
    push eax
    popfd
    pushfd
    pop eax

    xor eax, ecx            ; test if its changed
    jz NotChanged
    mov eax, 1              ; returns 1 if CPUID is present
    ret

  NotChanged:
    xor eax, eax            ; returns 0 if its not
    ret

is_cpuid endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

clive

I'd have to dig out the 386SX luggable, and stitch this into something that would run on it. ie DOS Extended, or Win 3.x VxD

The following is code I have in Watcom (DOS Extended) that is known to ID 386 and 486 class processors, and provide CPUID when available. The 486 test needs the stack to be aligned when it turns the AC bit on.

#pragma aux cpuid=\
"mov edx,0x300",\
"mov ebx,esp",\
"and esp,0xFFFFFFFC",\
"pushfd",\
"pop eax",\
"mov ecx,eax",\
"xor eax,0x00040000",\
"push eax",\
"popfd",\
"pushfd",\
"pop eax",\
"push ecx",\
"popfd",\
"mov esp,ebx",\
"xor eax,ecx",\
"jz cpuid_10",\
"mov edx,0x400",\
"pushfd",\
"pop eax",\
"mov ecx,eax",\
"xor eax,0x00200000",\
"push eax",\
"popfd",\
"pushfd",\
"pop eax",\
"push ecx",\
"popfd",\
"xor eax,ecx",\
"jz cpuid_10",\
"mov eax,1",\
"db 0x0F,0xA2",\
"mov edx,eax",\
"cpuid_10:",\
"mov eax,edx",\
modify [eax ebx edx ecx] value [ax];
It could be a random act of randomness. Those happen a lot as well.

dedndave

it looks right, Hutch
basically, if you can toggle EFLAGS bit 21, CPUID is supported
you could eliminate a couple lines of code...

    xor eax, ecx            ; test if its changed
    jz NotChanged           ; returns 0 if CPUID is not present
    mov eax, 1              ; returns 1 if CPUID is present

  NotChanged:
    ret

also, you can use the same stretch of code to toggle bit 18 at the same time
if that one toggles, it means you have a 486+, if not, it means it's a 386
that info can also help in Cyrix ID if you ever plan to add that

MichaelW

From my POV I don't have any really old systems. For a DOS version of the code running on an IBM 486 SLC2-66 the is_cpuid procedure returns 0.
eschew obfuscation

dedndave

        pushfd
        mov     eax,[esp]
        xor     eax,240000h  ;toggle bits 18 and 21
        mov     [esp],eax
        popfd
        pushfd
        pop     edx
        xor     eax,edx
        shr     eax,11

;AL = 0   => 486+
;AL = 80h => 386
;AH = 0   => CPUID supported
;AH = 4   => CPUID not supported


notice that no 386's support CPUID (i.e. both bits will be set for a 386)
so if EAX is any nonzero value, it means no CPUID

all pentiums support CPUID
so if AL is 0 and AH is not (EAX=400h), it means you have a 486

early 486's do not support CPUID
some late 486's do support CPUID (family = 4)

BlackVortex


dedndave

he wants to test it on a machine that doesn't support CPUID
if you can get into "8086 emulation mode", CPUID might not work, but it still might pass the test   :P

BlackVortex

Bochs is a hardcore emulator, isn't it ? I'm guessing they're emulating CPUID perfectly.

P.S.: You guys really like your CPUID thingy, don't ya ?

dedndave

QuoteBochs is a hardcore emulator, isn't it ? I'm guessing they're emulating CPUID perfectly.

hardcore ?
if you emulate the 8086, there is no CPUID instruction
but, the test to see if it is present is to toggle bit 21 of EFLAGS
not sure how well that would be emulated
i think the opcode would be the same as a 16-bit PUSHF/POPF

QuoteP.S.: You guys really like your CPUID thingy, don't ya ?

well, no - not really - lol
the documentation for CPUID is a bag of worms, at best
employing code that uses it is difficult to predict across a wide range of devices, especially non-Intel/AMD devices
i don't think anyone knows completely how it works


FORTRANS

Quote from: dedndave on April 24, 2010, 10:18:53 PM
hardcore ?
if you emulate the 8086, there is no CPUID instruction
but, the test to see if it is present is to toggle bit 21 of EFLAGS
not sure how well that would be emulated

Hi,

   Actually, In 8086, 80186, and 80286 there is no bit 21
in the flags.  So emulating it is moot.  So is running Hutch's
code though.

Cheers,

Steve N.

dedndave

true enough - what he really wants to test that particular code on is 386/486's
unless you get into ring 0, there is always the "may not work on Cyrix" clause
i have not been able to find any documentation on how different versions of windows handle the Cyrix issue
that is always a problem with CPUID - lack of documentation that is organized in a usable fashion
it would be nice if there were a database of complete CPUID dumps for every processor chip
i found a few things that had something along those lines - but they are never complete

FORTRANS

Hi,

   "The Undocumented PC" has an "is it Cyrix" routine (IIRC).
Do you want me to track that down?

Steve

dedndave

no Steve - i can ID a Cyrix CPU
that is fairly easy
you divide 5 by 2 - the flags across that specific combination will not change on a Cyrix
now - the tricky part is - which Cyrix CPU
if you know that, then you do not need to use CPUID on Cyrix chips to identify the features
you can pull them out of a table or otherwise use a set of constants
there are only, say, a half-dozen Cyrix chips

the problem with Cyrix is, the CPUID instruction may be disabled
the documentation is unclear if it also disables the EFLAGS bit 21 test
in order to enable CPUID on a Cyrix chip, you have to get to ring 0
afaik, there is no ms documentation to tell you what state the enable is left in

but, we could run the divide 5 by 2 test before testing for CPUID support
if it is a Cyrix chip, and we can tell which one without CPUID....
no need to use CPUID on it
we do know which features are supported by the different Cyrix chips

the first time a programmer has a customer try to run his code on a Cyrix, a problem will arise
either the routine will tell the app that a required feature is not supported that actually is
or, the program will crash with an invalid opcode exception
either way, the feedback will be, "The routine is broken"
the alternative is to say, "The routine does not support Cyrix chips"
which will be converted to, "The program does not support Cyrix chips"


dedndave

yes, Paul
that document will probably spell out what i just said
it makes it a pain in the arse
there are probably so few Cyrix chips in use
but, we have to accommodate them   :(
i sometimes wonder how many Cyrix chips have been sold, just for the sole purpose of software testing - lol

well - if i knew how to write a kernel mode driver to get to ring 0, i could write a proper routine   :P
it is clearly my fault
it seems rather stupid, if you ask me, to disable the CPUID instruction to begin with