【问题标题】:Error in my first assembly program (GCC Inline Assembly)我的第一个汇编程序出错(GCC 内联汇编)
【发布时间】:2011-03-08 00:33:41
【问题描述】:

经过大量互联网研究后,我在我的 C++ 程序中实现了一个小型汇编程序,以使用 cpuid 获取 CPU 的 L1 缓存大小。

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 位上完美运行。接下来我在我的 Mac 电脑上使用 GCC 4.0 尝试了这个,一定有一个错误,因为我的程序在 ComboBoxes 中显示奇怪的字符串,并且某些信号无法连接(Qt GUI)。

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

【问题讨论】:

  • 如果您使用调试器单步调试,您会看到什么情况?
  • @user363778:也许你应该时不时地接受一个答案?这是怎么做的:privat.rejbrand.se/howtoaccept.html

标签: gcc assembly g++ inline-assembly


【解决方案1】:

我认为 CPUID 实际上会破坏 EAX、EBX、ECX、EDX,所以这可能只是一个寄存器垃圾问题。以下代码似乎可以在 Mac OS X 上与 gcc 4.0.1 和 4.2.1 一起正常工作:

#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
$ 

【讨论】:

    【解决方案2】:

    我终于解决了这个问题。我在玩游戏时遇到编译器错误:“错误:PIC register '%ebx' 在 'asm' 中被破坏”,经过一些互联网研究后,我将代码修改为:

    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 也是一个不错的解决方案。 问候

    【讨论】:

    • 如上所述,小心这段代码。如果没有额外的clobbers,这是不正确的,并且您可能会遇到一些编译器优化级别的问题(即:特别是如果发生过程间优化和内联)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    相关资源
    最近更新 更多