20 March 2003

Wrote my first x86 assembly last night (I’ve only done M68000 until now). It’s nothing special, it just calls the CPUID instruction, which is available from kernel and userspace, and decodes one of the possible outputs:

#include <stdio.h>

/*
 * Generic CPUID function (stolen from Linux 2.5.59)
 */
static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
{
       __asm__("cpuid"
              : "=a" (*eax),
                "=b" (*ebx),
                "=c" (*ecx),
                "=d" (*edx)
              : "0" (op));
}

void registerToAscii(int reg)
{
  printf("%c", reg);
  reg = reg >> 8;
  printf("%c", reg);
  reg = reg >> 8;
  printf("%c", reg);
  reg = reg >> 8;
  printf("%c", reg);
}

int main(int argc, char *argv[])
{
  int a, b, c, d;

  printf("Calling cpuid with an input operand of zero\n\n");
  cpuid(0, &a, &b, &c, &d);

  printf("Got back: 0x%08x 0x%08x 0x%08x 0x%08x\n", a, b, c, d);
  printf("This decodes to: ");
  registerToAscii(b);
  registerToAscii(d);
  registerToAscii(c);
  printf("\n");
}

This gives the following on my Pentium III laptop:

#./cpuid
Calling cpuid with an input operand of zero

Got back: 0x00000002 0x756e6547 0x6c65746e 0x49656e69
This decodes to: GenuineIntel

I had no trouble finding instruction references for the Intel x86 chips. Where do I find the same documentation for the various AMD, Via, Cyrix et al chips floating around?

All of this was prompted by having a look at the x86info code, and the cpuid function in the 2.5.59 kernel tree I have been poking around in and deciding that I would like to understand at least a little more about what was happening. The hardest bit (and it isn’t very hard) is to determine what the GCC inline assembly syntax means. I recommend this IBM DeveloperWorks article…