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!

Edited 7 Years Ago by chrisname: n/a

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])

Edited 7 Years Ago by gerard4143: n/a

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);
}

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

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.

This article has been dead for over six months. Start a new discussion instead.