Page 1 of 1
Can't get CPU vendor
Posted: Wed Feb 06, 2019 9:51 pm
by deleted8917
I have this inline ASM function, that should return the CPU vendor:
Code: Select all
void printvendor(void)
{
/* This file (cpu.c) is compiled using -masm=intel */
asm volatile("mov eax, 0\t\n"
"cpuid\t\n"
"mov dword [vendor], ebx\n\t"
"mov dword [vendor+4], edx\n\t"
"mov dword [vendor+8], ecx\n\t");
println(vendor);
}
As the comment says, cpu.c is compilled under -masm=intel
I call the function, but nothing gets printed. Any idea?
thanks
Re: Can't get CPU vendor
Posted: Thu Feb 07, 2019 8:41 am
by Octocontrabass
Your inline assembly claims to have no side effects, so GCC doesn't know that you're clobbering four registers and modifying some memory.
You're also accessing a (global?) variable from inline assembly, which is discouraged since GCC's optimizations may not refer to said variable in ways you expect.
GCC provides cpuid.h which is recommended instead of using inline assembly. If you still want to use inline assembly,
you can look at cpuid.h for an example of how to do it.
Re: Can't get CPU vendor
Posted: Thu Feb 07, 2019 9:46 am
by deleted8917
I know that cpuid.h exists, but I have no idea how to use it.
btw, GCC inline ASM is so complex, and weird...
Re: Can't get CPU vendor
Posted: Thu Feb 07, 2019 12:20 pm
by bzt
hextakatt wrote:I know that cpuid.h exists, but I have no idea how to use it.
btw, GCC inline ASM is so complex, and weird...
If you're not familiar with inline asm, using cpuid.h seems pretty straightforward to me.
Code: Select all
#include <cpuid.h>
unsigned int eaxvar, ebxvar, ecxvar, edxvar;
__get_cpuid(0, &eaxvar, &ebxvar, &ecxvar, &edxvar);
Simple. Or, in your case more like
Code: Select all
unsigned char vendor[13];
memset(vendor, 0, sizeof(vendor));
__get_cpuid(0, &eaxvar, &vendor[0], &vendor[8], &vendor[4]);
println(vendor);
The cpuid.h defines exactly the inline asm you're looking for, which btw also answers your original question. Not that complex or weird as you may think.
Code: Select all
#define __cpuid(level, a, b, c, d) \
__asm__ ("cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level))
The "0" passes the level in eax as input (the hidden %%0 parameter in the template), and the ouput is saved in a=eax ("=a" refers to eax), b=ebx ("=b" refers to ebx), etc.
Cheers,
bzt
Re: Can't get CPU vendor
Posted: Thu Feb 07, 2019 1:01 pm
by iansjack
If you find inline assembler confusing (and I tend to agree with you), write the function in pure assembler and link it into your final program.
Re: Can't get CPU vendor
Posted: Thu Feb 07, 2019 6:32 pm
by deleted8917
bzt wrote:hextakatt wrote:I know that cpuid.h exists, but I have no idea how to use it.
btw, GCC inline ASM is so complex, and weird...
If you're not familiar with inline asm, using cpuid.h seems pretty straightforward to me.
Code: Select all
#include <cpuid.h>
unsigned int eaxvar, ebxvar, ecxvar, edxvar;
__get_cpuid(0, &eaxvar, &ebxvar, &ecxvar, &edxvar);
Simple. Or, in your case more like
Code: Select all
unsigned char vendor[13];
memset(vendor, 0, sizeof(vendor));
__get_cpuid(0, &eaxvar, &vendor[0], &vendor[8], &vendor[4]);
println(vendor);
The cpuid.h defines exactly the inline asm you're looking for, which btw also answers your original question. Not that complex or weird as you may think.
Code: Select all
#define __cpuid(level, a, b, c, d) \
__asm__ ("cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level))
The "0" passes the level in eax as input (the hidden %%0 parameter in the template), and the ouput is saved in a=eax ("=a" refers to eax), b=ebx ("=b" refers to ebx), etc.
Cheers,
bzt
Thanks! I hadn't found a way to use it!
iansjack wrote:If you find inline assembler confusing (and I tend to agree with you), write the function in pure assembler and link it into your final program.
Yes, GCC inline ASM is kinda weird and complex for me (at least). As you suggest in your reply, yes I tried to make the function in pure ASM, and then link it, but I couldn't make it work.
Thanks.