2010-06-24 165 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