Ожидалось выражение в операторе `__asm`

Я использую код из этой темы форума, чтобы получить информацию о семействе ЦП:

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

Если да, то какие заголовки/библиотеки мне не хватает? Если нет, то что я делаю неправильно?


person AStopher    schedule 07.09.2014    source источник
comment
Существуют различные синтаксисы asm. Ваш, кажется, для gcc (поправьте меня, если я ошибаюсь). Здесь вы можете прочитать о том, как Visual Studio хочет, чтобы это выглядело.   -  person Slyps    schedule 07.09.2014
comment
Не утруждая себя отладкой, я предполагаю, что ваш синтаксис asm неверен. Согласно MSDN, вы должны использовать __asm ​​вместо asm, используйте { } вместо (), и команды не должны быть в кавычках.   -  person Ryan Bemrose    schedule 07.09.2014
comment
@RyanBemrose Как упоминалось в вопросе, я изменил asm на __asm, но для ясности поместил туда исходный код. Я отредактирую его для __asm.   -  person AStopher    schedule 07.09.2014
comment
@Slyps Не могли бы вы дать ответ, как должен выглядеть код __asm в Visual Studio?   -  person AStopher    schedule 07.09.2014


Ответы (1)


В вашем примере кода используется синтаксис встроенной сборки в стиле GCC, который не поддерживается компилятором Microsoft. Хотя у Microsoft есть собственный синтаксис встроенного ассемблера, по возможности следует избегать его использования. Он поддерживается только 32-разрядным компилятором x86 и не поддерживается 64-разрядным компилятором или компиляторами, предназначенными для AMD или других архитектур ЦП. Кроме того, в отличие от синтаксиса встроенного ассемблера GCC, синтаксис Microsoft подчиняется ряду недокументированных правил, и даже если он написан «правильно», он может быть очень хрупким.

В вашем случае вы должны использовать встроенную функцию Microsoft для инструкции CPUID. Он будет работать как с 32-битной, так и с 64-битной версиями компилятора и не сломается из-за того, что вы изменили уровни оптимизации или обновили свой компилятор. Вы хотите использовать конкретную функцию __cpuid. В связанной документации должно быть ясно, как вы можете использовать ее для замены встроенного оператора сборки в вашей функции cpuid.

person Ross Ridge    schedule 07.09.2014
comment
В документации от Microsoft, похоже, нет никаких функций для получения семейства процессоров. - person AStopher; 07.09.2014
comment
Функцию __cpuid можно использовать для получения семейства ЦП, как в вашем примере кода. Просто замените оператор встроенной сборки вызовом __cpuid. Вам нужно передать массив в __cpuid. Скопируйте значения из массива в структуру и верните ее. - person Ross Ridge; 07.09.2014
comment
Компилятор MSVC определяет набор констант, в том числе зависящих от ЦП. арка Должна быть возможность использовать #ifndef _M_X86. - person Ryan Bemrose; 07.09.2014
comment
Кроме того, stackoverflow.com/questions/152016/ - person Ryan Bemrose; 07.09.2014