【问题标题】:Expected an expression in `__asm` statement`__asm` 语句中需要一个表达式
【发布时间】:2014-10-31 21:44:09
【问题描述】:

我正在使用来自this forum topic 的代码来获取 CPU 的系列信息:

#include <stdio.h>

struct cpuid_type {
    unsigned int eax;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;
};
typedef struct cpuid_type cpuid_t;

cpuid_t cpuid(unsigned int number) 
{
    cpuid_t result; 

    __asm("movl %4, %%eax; cpuid; movl %%eax, %0; movl %%ebx, %1; movl %%ecx, %2; movl %%edx, %3;"
        : "=m" (result.eax),
          "=m" (result.ebx),
          "=m" (result.ecx),
          "=m" (result.edx)               /* output */
        : "r"  (number)                   /* input */
        : "eax", "ebx", "ecx", "edx"      /* no changed registers except output registers */
        );

    return result;
}    

int main (int argc, const char * argv[]) 
{
    cpuid_t cpuid_registers;
    unsigned int cpu_family, cpu_model, cpu_stepping;

    cpuid_registers = cpuid(1);

    cpu_family   = 0xf & (cpuid_registers.eax>>8);
    cpu_model    = 0xf & (cpuid_registers.eax>>4);
    cpu_stepping = 0xf & cpuid_registers.eax;

    printf("CPUID (1): CPU is a %u86, Model %u, Stepping %u\n",
           cpu_family, cpu_model, cpu_stepping);


    return 0;
}

但是,Visual Studio 2013 给我一个“InteliSense:预期表达式”错误:

asm("movl %4, %%eax; cpuid; movl %%eax, %0; movl %%ebx, %1; movl %%ecx, %2; movl %%edx, %3;"
        : "=m" (result.eax), // <-- Error Here
          "=m" (result.ebx),
          "=m" (result.ecx),
          "=m" (result.edx)               /* output */
        : "r"  (number)                   /* input */
        : "eax", "ebx", "ecx", "edx"      /* no changed registers except output registers */
        );

正如 Visual Studio 2013 告诉我的 error C2290: C++ 'asm' syntax ignored. Use __asm.,我将 asm 更改为 __asm

我遇到的每个错误都与上面的代码块有关:

5   IntelliSense: expected a ')'
Error   2   error C2290: C++ 'asm' syntax ignored. Use __asm.   
Error   1   error C2143: syntax error : missing ')' before ':'
Error   3   error C2059: syntax error : ')'

由于我实际上是在使用上面提到的线程提供的代码而没有任何更改(除了__asm 编辑),我假设我没有包含不需要的所需库或标头将包含在早期版本的 Visual Studio 中。

如果是这样,我缺少哪些标头/库? 如果没有,我做错了什么?

【问题讨论】:

  • 有不同的 asm 语法。您的似乎适用于 gcc(如果我错了,请纠正我)。 Here 你可以阅读 Visual Studio 想要的样子。
  • 无需调试,我假设您的“asm”语法是错误的。根据MSDN,你应该使用“__asm”而不是“asm”,使用{}而不是(),并且命令不能用引号引起来。
  • @RyanBemrose 如问题中所述,我已将asm 更改为__asm,但为了清楚起见,我将原始代码放在那里。我会为__asm编辑它。
  • @Slyps 请您提供一个答案,说明 __asm 代码在 Visual Studio 下应该是什么样子?

标签: c++ assembly visual-studio-2013 compiler-errors cpuid


【解决方案1】:

您的示例代码使用了 Microsoft 编译器不支持的 GCC 样式的内联汇编语法。虽然 Microsoft 有自己的内联汇编语法,但您应该尽可能避免使用它。它仅受 32 位 x86 编译器支持,不支持 64 位编译器或针对 AMD 或其他 CPU 架构的编译器。此外,与 GCC 的内联汇编语法不同,Microsoft 的语法受制于许多未记录的规则,即使“正确”编写也可能非常脆弱。

在您的情况下,您应该将 Microsoft 的内在函数用于 CPUID 指令。它适用于 32 位和 64 位版本的编译器,并且不会因为您更改优化级别或升级编译器而中断。您要使用的具体功能是__cpuid。链接的文档应该清楚说明如何使用它来替换 cpuid 函数中的内联汇编语句。

【讨论】:

  • 微软的文档好像没有获取CPU族的功能。
  • __cpuid 函数可用于获取 CPU 系列,就像在您的示例代码中一样。只需将内联汇编语句替换为对__cpuid 的调用即可。您需要将数组传递给 __cpuid。将数组中的值复制到结构中并返回。
  • MSVC 编译器定义了一堆constants,包括基于 CPU 架构的。应该可以使用#ifndef _M_X86。
猜你喜欢
  • 2023-01-16
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 2023-03-13
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多