954,490 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

CPUID :)

Hi :)

I'm trying to get the vendor ID using the CPUID opcode. Again, this is inline ASM with C; but it's the ASM that I need help with. The C is fine AFAIK.

I'm not sure if it's the way I'm trying to do this, or if my CPU simply doesn't support CPUID...

char* getCPUID(void) {
    int vendor[3];
    char vstring[12 + 1];

    /* Get vendor string: */
    asm("mov %0, %%eax\n\t"
        "cpuid\n\t"
        "cmp $3, %%eax\n\t" /* If eax < 3, CPU doesn't support CPUID... */
        "jl dont_bother\n\t" /* So we can't CPUID :( */
        "mov %%ebx, %0\n\t"
        "mov %%ecx, %1\n\t"
        "mov %%edx, %2\n\t"
        "dont_bother:\n\t"
        "mov $-1, %0"
        :"=r"(vendor[0]), "=r"(vendor[1]), "=r"(vendor[2])
       );
       
   if (vendor[0] == -1) {
       return "Error: CPU doesn't support CPUID!";
   }

   /* Store in vstring; 12 char string results */
   memcpy(&(vstring[0]), &(vendor[0]), sizeof(int));
   memcpy(&(vstring[4]), &(vendor[1]), sizeof(int));
   memcpy(&(vstring[8]), &(vendor[2]), sizeof(int));

   /* Make sure string is NULL-terminated */
   vstring[12] = '\0';
   
   return getManufacturer(vstring); /* Function simply compares vstring to some
                                       known vendor strings. */
}

... but my error message is printed. Is it my ASM, or the CPU?
I'm hoping it's the ASM...$ ./a.out
Manufacturer: Error: CPU doesn't support CPUID!

chrisname
Light Poster
26 posts since Oct 2009
Reputation Points: 10
Solved Threads: 0
 

Hi :)

I'm trying to get the vendor ID using the CPUID opcode. Again, this is inline ASM with C; but it's the ASM that I need help with. The C is fine AFAIK.

I'm not sure if it's the way I'm trying to do this, or if my CPU simply doesn't support CPUID...

char* getCPUID(void) {
    int vendor[3];
    char vstring[12 + 1];

    /* Get vendor string: */
    asm("mov %0, %%eax\n\t"
        "cpuid\n\t"
        "cmp $3, %%eax\n\t" /* If eax < 3, CPU doesn't support CPUID... */
        "jl dont_bother\n\t" /* So we can't CPUID :( */
        "mov %%ebx, %0\n\t"
        "mov %%ecx, %1\n\t"
        "mov %%edx, %2\n\t"
        "dont_bother:\n\t"
        "mov $-1, %0"
        :"=r"(vendor[0]), "=r"(vendor[1]), "=r"(vendor[2])
       );
       
   if (vendor[0] == -1) {
       return "Error: CPU doesn't support CPUID!";
   }

   /* Store in vstring; 12 char string results */
   memcpy(&(vstring[0]), &(vendor[0]), sizeof(int));
   memcpy(&(vstring[4]), &(vendor[1]), sizeof(int));
   memcpy(&(vstring[8]), &(vendor[2]), sizeof(int));

   /* Make sure string is NULL-terminated */
   vstring[12] = '\0';
   
   return getManufacturer(vstring); /* Function simply compares vstring to some
                                       known vendor strings. */
}

... but my error message is printed. Is it my ASM, or the CPU? I'm hoping it's the ASM...

In your inline the "jl dont_bother" may not be supported. I always use something like

"jmp 0f\n\t"
.
.
.
"0:\n\t"


Also, your lines

"mov %%ebx, %0\n\t"
  "mov %%ecx, %1\n\t"
  "mov %%edx, %2\n\t"


each of these lines are moving 4 bytes into the character array but you only increment it by one byte as seen below

:"=r"(vendor[0]), "=r"(vendor[1]), "=r"(vendor[2])

shouldn't this be

:"=r"(vendor[0]), "=r"(vendor[4]), "=r"(vendor[8])


Actually I think you have your variables mixed up, the line above should be

:"=r"(vstring[0]), "=r"(vstring[4]), "=r"(vstring[8])
gerard4143
Nearly a Posting Maven
2,272 posts since Jan 2008
Reputation Points: 512
Solved Threads: 387
 

Here's a simplified version of what your trying to do...Its using 64 bit Intel/AMD

#include <stdio.h>
#include <stdlib.h>

void findit()
{
	char cpustuff[12];
	void *vptr = (void*)&cpustuff[0];

	__asm__ __volatile__
	(
	 	"xorl	%%eax, %%eax\n\t"
		"cpuid\n\t"
		"movq	%0, %%rsi\n\t"
		"movl	%%ebx, (%%rsi)\n\t"
		"movl	%%edx, 4(%%rsi)\n\t"
		"movl	%%ecx, 8(%%rsi)\n\t"
		:"=m"(vptr) 
	);
	fprintf(stdout, "%s\n", cpustuff);
}

int main(int argc, char**argv)
{
	findit();
	exit(EXIT_SUCCESS);
}
gerard4143
Nearly a Posting Maven
2,272 posts since Jan 2008
Reputation Points: 512
Solved Threads: 387
 

Lol, thank you! :)

I feel silly now :P

chrisname
Light Poster
26 posts since Oct 2009
Reputation Points: 10
Solved Threads: 0
 

Lol, thank you! :)

I feel silly now :P

Don't, assembly can be a hard step to make...Just remember your dealing with either addresses or numbers...Gerard4143

gerard4143
Nearly a Posting Maven
2,272 posts since Jan 2008
Reputation Points: 512
Solved Threads: 387
 
Don't, assembly can be a hard step to make...Just remember your dealing with either addresses or numbers...Gerard4143


Yeah; it's difficult all right :P
Easy to learn enough opcodes to get started, and the syntax is easy (Intel is, AT&T took a little getting used to but I prefer it now -- you can tell more what's going on because instead of just "mov" you get "movl", "movq", etc.), but it's just hard to implement and the semantics are crazy.

Anyway, thanks for helping. I'll try that CPUID code now.

chrisname
Light Poster
26 posts since Oct 2009
Reputation Points: 10
Solved Threads: 0
 

Thanks! It worked!

chrisname
Light Poster
26 posts since Oct 2009
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You