开发者

Error in my first assembly program (GCC Inline Assembly)

开发者 https://www.devze.com 2023-01-04 12:28 出处:网络
After a lot of internet research I implemented a small assembler routine in my C++ program to get the CPU\'s L1 cache size using cpuid.

After a lot of internet research I implemented a small assembler routine in my C++ program to get the CPU's L1 cache size using cpuid.

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;
开发者_JAVA技巧}

It works perfectly on Windows 7 64 bit with MinGW (GCC, G++). Next I tried this on my Mac computer using GCC 4.0 and there must be an error somewhere because my program shows strange strings in the ComboBoxes and some signals cannot be connected (Qt GUI).

This is my first assembler program, I hope someone can give me a hint, Thanks!


I think that CPUID actually clobbers EAX, EBX, ECX, EDX, so it's probably just a register trashing problem. The following code appears to work OK with gcc 4.0.1 and 4.2.1 on Mac OS X:

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

Note that you need to compile with -fno-pic as EBX is reserved when PIC is enabled. (Either that or you need to take steps to save and restore 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
$ 


I finally resolved the problem. I got a compiler error while playing around: "error: PIC register '%ebx' clobbered in 'asm'" and after some internet research I modified my code to:

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;

}

Thanks Paul, The compiler option -fno-pic is a nice solution too. Greetings

0

精彩评论

暂无评论...
验证码 换一张
取 消