Search code examples
cassemblycpuid

Inconsistent CPUID results with different callers for some EAX values


unsigned int a, b;
a = 0;
b = 0;

for(a=0; a<6; a++)
{
    __asm__("cpuid"
        :"=a"(b)                 /** EAX into b (output) */
        :"0"(a)                  /** a into EAX (input) */
        :"%ebx","%ecx","%edx");  /** clobbered registers */
    printf("a=%d, b=0x%x", a, b);
}

Above code prints value of a and b.

In Ubuntu 22, this portion of code I am using for 2 projects. One is quite small one and other is bigger one. I see values of a and b are printed in small and big projects as below.

a, b values in small project

a=0, b=0x20
a=1, b=0xb06a3
a=2, b=0xfeff01
a=3, b=0x0
a=4, b=0x0
a=5, b=0x40
a=6, b=0xdf8ff7

a, b values in bigger project

a=0, b=0x20
a=1, b=0xb06a3
a=2, b=0xfeff01
a=3, b=0x0
a=4, b=0x7c01c143
a=5, b=0x40
a=6, b=0xdf8ff7

You can see in line starting with a=4, b value is different for above two cases. I am surprised why values becoming different, ideally values should remain same even if this code is run from different projects.

Can somebody please help me to understand how come values are different.


Solution

  • https://www.felixcloutier.com/x86/cpuid

    4 is Deterministic Cache Parameters Leaf

    Information returned depends on the value in ECX. A 0 result means that ECX did not contain the index of a valid cache.

    Try setting ECX to the same value for both and the results should stabilize as well.

    Example:

    __asm__("movl $0,%%ecx;\n\t"
            "cpuid"
        :"=a"(b)                 /** EAX into b (output) */
        :"0"(a)                  /** a into EAX (input) */
        :"%ebx","%ecx","%edx");  /** clobbered registers */