2

I trying to convert function "__cpuid" from С language to C++. I have a problem that the g++ compiler does not work with Intel assembler.

I'm trying to translate this code:

__asm
    {
        mov    esi, CPUInfo
        mov    eax, InfoType
        xor ecx, ecx
        cpuid
        mov    dword ptr[esi + 0], eax
        mov    dword ptr[esi + 4], ebx
        mov    dword ptr[esi + 8], ecx
        mov    dword ptr[esi + 12], edx
    }

I tried to do it using examples from the Internet, I got this code, but it doesn't work:

__asm
    (


            "movl   %CPUInfo,%esi\n"
            "movl   %InfoType,%eax\n"
            "xorl   %ecx,%ecx\n"
            "cpuid\n"
            "movl   %eax,0(%esi)\n"
            "movl   %ebx,4(%esi))\n"
            "movl   %ecx,8(%esi)\n"
            "movl   %edx,12(%esi)\n"
             :"=r"(CPUInfo)
 

    );
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 2
    this is all inline assembly and has nothing to do with C or C++, so `convert function "__cpuid" from С language to C++` makes zero sense – phuclv Jun 25 '22 at 14:27
  • 2
    Perhaps your compiler have an *intrinsic* function ready for you to use? Also see e.g. [Intrinsics for CPUID like informations?](https://stackoverflow.com/questions/17758409/intrinsics-for-cpuid-like-informations). – Some programmer dude Jun 25 '22 at 14:28
  • [gcc inline assembly documentation](https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html#Using-Assembly-Language-with-C). Note in particular the syntax for inserting parameters. – Raymond Chen Jun 25 '22 at 14:30
  • 1
    The latest AT&T C++ compiler was released in 1984. It may have troubles with this assembly anyway. – Eljay Jun 25 '22 at 15:04
  • Well: (1) all the `%` before register names should be `%%`; (2) `%CPUInfo` should be `%0` because you are not using named parameters; (3) `%InfoType` does not exist, maybe you want to add it as input; (4) `CPUInfo` should be in the list of input operands; (5) all those `movl` after `cpuid` make no sense if you are not binding `esi` to something like an array or struct. (6) you need to clobber any register you touch. -- All in all... need more context around the code. [This](https://stackoverflow.com/a/61310032/3889449) is what you probably want. – Marco Bonelli Jun 25 '22 at 15:16
  • If you are just wanting to get the cpuid, https://stackoverflow.com/questions/14266772/how-do-i-call-cpuid-in-linux will do the job – abligh Jun 25 '22 at 15:25
  • I can try to help you, but I'm going to need you to [edit] your question and post the full function and all structures in question. You can also search for other cpuid examples on this site. There are dozens, if not hundreds of questions almost identical to yours. – fuz Jun 25 '22 at 16:15
  • I suspect your question is really "how do I convert Microsoft inline assembly to GNU inline assembly"?. Is this correct? – Joseph Sible-Reinstate Monica Jun 25 '22 at 20:08

2 Answers2

4
void cpuid(int InfoType, int *CPUInfo) {
  int a = InfoType;
  int c = 0;
  int b, d;
  __asm__ (
    "cpuid"
    : "+a"(a), "=b"(b), "+c"(c), "=d"(d)
  );
  CPUInfo[0] = a;
  CPUInfo[1] = b;
  CPUInfo[2] = c;
  CPUInfo[3] = d;
}

a, b, c, and d each binds to eax, ebx, ecx, and edx register. The GCC docs explains how this works in detail.

xiver77
  • 2,162
  • 1
  • 2
  • 12
  • See also https://stackoverflow.com/tags/inline-assembly/info. And BTW, the reason this answer used `"+c"(c)` to make ECX a read/write operand is that some CPUID leaves use ECX as another selector within that leaf. e.g. https://www.sandpile.org/x86/cpuid.htm#level_0000_0004h to query info about different levels of caches. – Peter Cordes Jun 25 '22 at 22:28
  • Normally you'd use the functions from `cpuid.h` ([How do I call "cpuid" in Linux?](https://stackoverflow.com/q/14266772)) instead of hand-rolling your own inline asm, but yes this is a useful exercise in GNU C inline asm: only the special / interesting instruction goes in the template, you use input / output operands to tell the compiler what instructions to generate around it. If your template starts or ends with `mov` instructions, usually that means you're doing it wrong. – Peter Cordes Jun 25 '22 at 22:30
-2

On linux (and in many other platforms, non-linux, non-gcc), you can assemble the intel assembly code into an object file with assembler such as nasm. Then you can link your assembly object into the application without need of mixing messages or assembly language syntax.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
L_R
  • 170
  • 11
  • 1
    That is not really going to help OP with figuring out the whole inline assembly business. – fuz Jun 25 '22 at 16:15
  • 1
    @fuz, inline assembly is a gcc dependency that should be avoided, so why not telling th OP about the all times available possibility of writing functions completely in assembler instead of tainting C code with compiler extensions? I think I'm going to upvote this answer, as IMHO it has been unjustly downvoted. – Luis Colorado Jun 26 '22 at 10:56