对于某些 EAX 值,不同的调用方会导致 CPUID 不一致

Inconsistent CPUID results with different callers for some EAX values

提问人:Kamal Palei 提问时间:11/1/2023 最后编辑:Peter CordesKamal Palei 更新时间:11/2/2023 访问量:86

问:

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

上面的代码打印了 a 和 b 的值。

在 Ubuntu 22 中,我用于 2 个项目的这部分代码。一个很小,另一个很大。我看到 a 和 b 的值打印在小型和大型项目中,如下所示。

小项目中的 a、b 值

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值在更大的项目中

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

您可以看到从 a=4 开始,上述两种情况下的 b 值不同。我很惊讶为什么值会变得不同,理想情况下,即使此代码从不同的项目运行,值也应该保持不变。

有人可以帮我理解为什么价值观会有所不同。

C 程序集 CPUID

评论

0赞 Peter Cordes 11/1/2023
ECX 是某些 EAX 值的 CPUID 的另一个输入。在 GNU C 中,你可以只使用 like 的函数,它接受两个输入参数。 (github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/cpuid.h / [CPUID 的内部函数,类似信息?cpuid.h__get_cpuid_count)

答:

3赞 teapot418 11/1/2023 #1

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

4 是确定性缓存参数叶

返回的信息取决于 ECX 中的值。0 结果表示 ECX 不包含有效缓存的索引。

尝试将两者的 ECX 设置为相同的值,结果也应该稳定下来。

例:

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

评论

0赞 Kamal Palei 11/1/2023
谢谢,如何设置 ECX 值。这是一个现有的代码,我不知道如何设置 ECX 值。请举个例子。
3赞 Peter Cordes 11/1/2023
@Austin:如果您不了解内联 asm 或不知道如何修改它,请将其替换为 from GCC 的 .应编译为相同的 asm。(至少对于 x86-64;我认为,在 32 位代码中,每次调用至少一些包装函数都会首先检查 CPUID 的可用性。__get_cpuid_count()cpuid.h
0赞 Kamal Palei 11/1/2023
谢谢。如果我必须设置 ECX 值,如何做到这一点,任何提示都非常感谢。
0赞 teapot418 11/1/2023
@Austin刚刚添加了一个零的例子。语法可能有点傻,我对内联汇编不太熟悉。更多详情请见 ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
0赞 Kamal Palei 11/2/2023
你的例子效果很好。接受你的完美答案。