0

I'm trying to get a function that prints out the CPU's name/vendor but when I try it I end up getting "GenuntellineI".

Here is the function:

void PrintProcessingDeviceType()
{
    uint32_t regs[4];

    #ifdef _WIN32
    __cpuid((int*)regs, 0);
    #else
    asm volatile ("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (0), "c" (0));
    #endif

    std::cout << std::string((const char*)&regs, 16) << std::endl;
}

Both paths (with _WIN32 defined and when it's not) result in this error occurring. Is this a problem with CPUID just not being correct, did I do something wrong, or what?

Therhang
  • 825
  • 1
  • 9
  • 15
  • Try running the msdn example and see if the error persists: https://msdn.microsoft.com/en-us/library/hskdteyh.aspx?f=255&MSPPError=-2147217396 – Beta Carotin Jul 21 '15 at 12:01
  • @BetaCarotin When I try to compile the MSDN example I get the error "__cpuidex was not declared in this scope". So that's out of the question. – Therhang Jul 21 '15 at 12:16

3 Answers3

4

Why would you expect something different?
Consult the Intel Manuals when an instruction seems to behave differently from what you expected.

CPUID with EAX=0 results

3

This seems to be a quirk of the CPUID function, see http://www.microbe.cz/docs/CPUID.pdf (Section 2.1.1) for details. (For a loose definition of quirk; it is not marked as such, but easily overlooked.)

It returns the first 4 bytes in the register EBX, the next 4 bytes in EDX and the last ones in ECX. Note two things: First, the result of EAX (regs[0]) does not contain any characters of the model name, so you should only print it starting at regs[1]. Second, the order of the last two registers is "reversed". If you swap the respective entries of your array, you should get the correct string (i.e. regs[2]and regs[3]).

anderas
  • 5,744
  • 30
  • 49
  • Interestingly enough, while swapping `regs[2]` and `regs[3]` did work by making the only visible text printing to the console being "GenuineIntel" (other than some weird spacing), removing `regs[0]` or doing any other modification causes the string to change dramatically, sometimes even shrink (or so it appears from the console window). – Therhang Jul 21 '15 at 12:25
  • Strange. But then, I haven't been able to try it right now, and wanted to share what I was able to find in the PDF :-) If you find out why the strange behaviour occurs, please post that! – anderas Jul 21 '15 at 12:37
1

You can think of CPUID instruction as a function which takes as an argument value passed via EAX register ie. what CPUID returns solely depends on what is in your EAX prior to executing CPUID.

In your case before CPUID was executed your EAX was equal to 0. This way CPUID returns basic processor info which was GenuinIntel on your machine. AMD processors will return AuthenticAMD in same scenario.

Since every processor is slightly different CPUID's behavior depends on your CPU so after obtaining basic CPU info you must use CPUID's specific cunctions to learn more about CPU features etc. For this you need particular CPU doc describing CPUID.

anderas already gave you CPUID pdf for Intel. Here you can get for AMD:

http://support.amd.com/TechDocs/25481.pdf#search=cpuid

Artur
  • 7,038
  • 2
  • 25
  • 39