2010-06-24 152 views
4

经过大量的网络研究之后,我在C++程序中实现了一个小型汇编程序,以便使用cpuid获得CPU的L1高速缓存大小。我的第一个汇编程序错误(GCC内联汇编)

int CPUID_getL1CacheSize() { 

    int l1CacheSize = -1; 

    asm ("mov $5, %%eax\n\t" // EAX=80000005h: L1 Cache and TLB Identifiers 
      "cpuid\n\t" 
      "mov %%eax, %0"  // eax into l1CacheSize 
      : "=r"(l1CacheSize) // output 
      :      // no input 
      : "%eax"    // clobbered register 
     ); 

    return l1CacheSize; 
} 

它使用MinGW(GCC,G ++)在Windows 7 64位上完美工作。接下来,我使用GCC 4.0在我的Mac电脑上尝试了这一点,并且在某处出现了错误,因为我的程序在ComboBox中显示了奇怪的字符串,并且某些信号无法连接(Qt GUI)。

这是我的第一个汇编程序,希望有人能给我一个提示,谢谢!

+1

如果您使用调试器来浏览它,您会看到什么情况? – 2010-06-24 20:49:53

+2

@ user363778:也许你应该不时地接受答案?这是如何做到这一点:http://privat.rejbrand.se/howtoaccept.html – 2010-06-24 21:13:12

回答

5

我认为CPUID实际上是破坏了EAX,EBX,ECX,EDX,所以它可能只是一个注册垃圾问题。下面的代码将出现在Mac OS X上使用gcc 4.0.1和4.2.1上班OK:

#include <stdio.h> 

int CPUID_getL1CacheSize() 
{ 
    int l1CacheSize = -1; 

    asm ("mov $5, %%eax\n\t" // EAX=80000005h: L1 Cache and TLB Identifiers 
      "cpuid\n\t" 
      "mov %%eax, %0"  // eax into l1CacheSize 
      : "=r"(l1CacheSize) // output 
      :      // no input 
      : "%eax", "%ebx", "%ecx", "%edx" // clobbered registers 
     ); 

    return l1CacheSize; 
} 

int main(void) 
{ 
    printf("CPUID_getL1CacheSize = %d\n", CPUID_getL1CacheSize()); 
    return 0; 
} 

请注意,你需要-fno-pic编译为启用PIC时EBX被保留。 (或者你需要采取措施保存和恢复EBX)。

$ gcc-4.0 -Wall -fno-pic cpuid2.c -o cpuid2 
$ ./cpuid2 
CPUID_getL1CacheSize = 64 
$ gcc-4.2 -Wall -fno-pic cpuid2.c -o cpuid2 
$ ./cpuid2 
CPUID_getL1CacheSize = 64 
$ 
0

我终于解决了这个问题。我得到一个编译器错误,而玩耍:“错误:PIC注册‘%EBX’在‘汇编’惨败”之后一些互联网研究,我修改了我的代码:

INT CPUID_getL1CacheSize(){

int l1CacheSize = -1; 

asm volatile ("mov $5, %%eax\n\t" 
       "pushl %%ebx; cpuid; popl %%ebx\n\t" 
       "mov %%eax, %0" 
       : "=r"(l1CacheSize) 
       : 
       : "%eax" 
       ); 

return l1CacheSize; 

}

感谢Paul,编译选项-fno-pic也是一个不错的解决方案。 问候

+1

如上所述要小心这个代码。没有额外的clobbers是不正确的,你可能会遇到一些编译器优化级别问题(例如:特别是如果程序间优化和内联发生的话)。 – 2011-06-24 11:21:26