“__asm”语句中应包含表达式

Expected an expression in `__asm` statement

本文关键字:包含 表达式 语句 asm      更新时间:2023-10-16

我使用论坛主题中的代码来获取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 %un",
           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的早期版本中。

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

您的示例代码使用的是GCC风格的内联汇编语法,而Microsoft编译器不支持这种语法。虽然Microsoft有自己的内联程序集语法,但您应该尽可能避免使用它。它只支持32位x86编译器,不支持64位编译器或针对AMD或其他CPU架构的编译器。此外,与GCC的内联汇编语法不同,微软的语法受到许多未记录的规则的约束,即使写得"正确",也可能非常脆弱。

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