9

While writing new code for Windows, I stumbled upon _cpuinfo() from the Windows API. As I am mainly dealing with a Linux environment (GCC) I want to have access to the CPUInfo.

I have tried the following:

#include <iostream>
 
int main()
{
  int a, b;
 
  for (a = 0; a < 5; a++)
  {
    __asm ( "mov %1, %%eax; "            // a into eax
          "cpuid;"
          "mov %%eax, %0;"             // eax into b
          :"=r"(b)                     // output
          :"r"(a)                      // input
          :"%eax","%ebx","%ecx","%edx" // clobbered register
         );
    std::cout << "The CPUID level " << a << " gives EAX= " << b << '\n';
  }
 
  return 0;
}

This use assembly but I don't want to re-invent the wheel. Is there any other way to implement CPUInfo without assembly?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
TheBlueCat
  • 1,147
  • 5
  • 19
  • 38
  • 1
    So, this is g++ I guess. And x86? You should say. What is the question in any case? You told us what you are doing, and shown the code. But there's no question. – David Heffernan Jan 10 '13 at 20:39
  • @JerryCoffin I'm running Linux (as in this will be the Linux section to determine the CPU of the computer executing the code). I already have the Windows version/section nailed with the _cpuinfo() function from the Win API. That's my point. – TheBlueCat Jan 10 '13 at 20:39
  • @DavidHeffernan See my updated post, I neglected to add the Compiler errors. – TheBlueCat Jan 10 '13 at 20:41
  • I've edited the question to reflect (what I think) is the intended question. Feel free to roll it back if I'm wrong. – Mysticial Jan 10 '13 at 20:42
  • yet again, a suitable question is downvoted, even when there's no clear answer (there isn't any). – TheBlueCat Jan 10 '13 at 20:42
  • If my edit is accurate, then let me know and I'll post an answer. – Mysticial Jan 10 '13 at 20:42
  • @Mysticial I know how to implement it for gcc/linux. I'm recieveing compile errors which I do not know how to get rid of, thus make the damn thing build. – TheBlueCat Jan 10 '13 at 20:43
  • 2
    I don't know why you complain about a downvote. Now, I didn't downvote, and I see that it has been removed. But the original question omitted details of compilers, failed to provide error messages and did not ask a question. So somebody downvoted you. That's to be expected. Don't blame the downvoter. Fix the question. Then you'll get up votes. – David Heffernan Jan 10 '13 at 20:46
  • @DavidHeffernan gave a good answer; depending on what you want, it may be easier to read the data from `/proc/cpuinfo`. – Jerry Coffin Jan 10 '13 at 20:51
  • I rolled the question back. Please don't change it like you did. If you want to add your own answer do so. But if you remove all the errors from the question, then the answers look stupid. – David Heffernan Jan 10 '13 at 20:52
  • @DavidHeffernan I disagree. The title states 'How do I call “cpuid” in Linux?'. The compiler errors where a typo from switching git branches when I tested this code out; ie, not on production code. The answer is not relevant to compiler erros, whereas, it is relevant to 'how do I call cpuinfo from cpuid.h. Sorry, I'm going to edit my question for clarity. – TheBlueCat Jan 10 '13 at 20:56
  • Your latest edit is different from the one I reverted. This one is better. But I'd still perfer to see the original code with the compiler error because one of the answers now looks very odd. It wasn't @user's fault. They just answered what was there at the time. So I'd sooner see your edit add to the original. – David Heffernan Jan 10 '13 at 21:06
  • @DavidHeffernan I'll add the compiler errors in with a note. – TheBlueCat Jan 10 '13 at 21:09
  • The compile errors surely need to match the code in the question, with the stray ; but maybe it's not worth worrying any more. I suspect I'm annoying you now! ;-) – David Heffernan Jan 10 '13 at 21:11
  • @DavidHeffernan I was thinking the same. The post would be cluttered with the code. I think my asm approach is pretty novel, it would surely increase the value of the thread. users's post answers the typo well, not to mention with the code examples; although it currently at the footer. I feel the reader could piece it together , though. – TheBlueCat Jan 10 '13 at 21:13
  • @TheBlueCat It's not that novel, I've seen this answer on no less than 6 similar questions today while looking for a decent example using the C/C++ that is built in. Rather than various people's adhoc inline assembly answers :-) – UpAndAdam Mar 11 '14 at 22:13

2 Answers2

38

Since you are compiling with GCC then you can include cpuid.h which declares these functions:

/* Return highest supported input value for cpuid instruction.  ext can
   be either 0x0 or 0x8000000 to return highest supported value for
   basic or extended cpuid information.  Function returns 0 if cpuid
   is not supported or whatever cpuid returns in eax register.  If sig
   pointer is non-null, then first four bytes of the signature
   (as found in ebx register) are returned in location pointed by sig.  */
unsigned int __get_cpuid_max (unsigned int __ext, unsigned int *__sig)

/* Return cpuid data for requested cpuid level, as found in returned
   eax, ebx, ecx and edx registers.  The function checks if cpuid is
   supported and returns 1 for valid cpuid information or 0 for
   unsupported cpuid level.  All pointers are required to be non-null.  */
int __get_cpuid (unsigned int __level,
    unsigned int *__eax, unsigned int *__ebx,
    unsigned int *__ecx, unsigned int *__edx)

You don't need to, and should not, re-implement this functionality.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 9
    +1 Didn't know that header existed. I've always done it with a bit of inline assembly. – Mysticial Jan 10 '13 at 20:47
  • Sure. I managed to get the piece to compile anyway. Notwithstanding, why should I not re-implement this? Besides time-saving? – TheBlueCat Jan 10 '13 at 20:48
  • 1
    @Mysticial This is where my total ignorance of GCC and Linux comes in handy. I had to google for the answer! – David Heffernan Jan 10 '13 at 20:48
  • 7
    Basic rule of development is to re-use rather than re-implement. Do you write your own `printf`? Or your own `strcmp`? Do you write your own `std::string`? – David Heffernan Jan 10 '13 at 20:49
  • @DavidHeffernan Yet another reason why "ignorance" fuels new ideas... ahaha – Mysticial Jan 10 '13 at 20:50
  • 1
    Can you provide / include an example usage? And potentially add the return types as well :-P – UpAndAdam Mar 11 '14 at 22:12
  • @UpAndAdam Fair comment, esp. the return values. I've added these. I also included the comments from the header file that document how to call them. I don't have a suitable compiler at hand so don't want to try my hand at a usage example and get it wrong. – David Heffernan Mar 11 '14 at 22:39
  • No problem, much appreciated! I saw those comments as well in the header file and was hoping they made slightly more sense to someone else :-p I'll just have to keep on reading some more – UpAndAdam Mar 12 '14 at 14:16
  • @UpAndAdam I think you need to read the Intel docs for CPUID to make sense of them. – David Heffernan Mar 12 '14 at 14:21
  • I have been trying to of course, there's just lots of it and each reads a little differently than the last :-P Thanks again for the help! – UpAndAdam Mar 12 '14 at 15:26
  • 2
    There's only one official Intel doc. – David Heffernan Mar 12 '14 at 15:28
  • hello for level 1, eax=1 my ebx register keeps outputting random values, is there anyway I can check if for a level the register is relevant or not. – itsnevertoobadtoaskforhelp Aug 11 '16 at 16:43
8
for (a =0; a < 5; ++a;)

There should only be two semicolons there. You've got three.

This is basic C/C++ syntax; the CPUID is a red herring.

user9876
  • 10,954
  • 6
  • 44
  • 66
  • typo. I fixed it before I posted, for some reason it got back into there. I changed branches on Git, that's probably the reason. But yes, I do know this 'basic syntax'. – TheBlueCat Jan 10 '13 at 20:47
  • 9
    But the errors you posted are caused by this typo. If you've fixed that and are still having problems, please update the list of errors. – user9876 Jan 10 '13 at 20:48
  • @user9876: I fixed the question to remove the old error messages; the current code in the question compiles without any warnings. (https://godbolt.org/z/ezzTW7c1a). It's clunky and only produces the EAX output, but that's why it makes sense to ask for something better. Anyway, you can finally delete this answer now that it's fully irrelevant to the current question. – Peter Cordes Feb 25 '22 at 01:04