>
>
Распространенная ошибка при компиляции …

Андрей Карпов
Статей: 671

Распространенная ошибка при компиляции 64-битного приложения: error C4235, Assembler

Visual C++ не поддерживает 64-битный встроенный ассемблер.

В результате вы получите ошибку при попытке компиляции следующего кода:

void waitvrt(void)
{
  __asm {
      mov  dx,3dah
  VRT:
      in    al,dx
      test  al,8
      jnz    VRT
  NoVRT:
      in    al,dx
      test  al,8
      jz    NoVRT
  }     
}
1>.\Third_party\Src\CreditsThread.cpp(111) :
error C4235: nonstandard extension used : 
'__asm' keyword not supported on this architecture

Если вам все же необходимо использовать ассемблерный код, то можно воспользоваться внешним 64-битным ассемблером, например, MASM.

Но скорее всего вам следует переписать данный код на языке Си/Си++. Высока вероятность, что ассемблерный код уже устарел и рационально использовать современные функции операционной системы или конструкции языка Си/Си++. Использование ассемблера для оптимизации в настоящее время редко оправдано, так как компилятор Visual C++ в большинстве случаев создаст достаточно эффективный код. Также не забывайте про возможность использования intrinsic-функций.

Intrinsic-функции - это специальные системно-зависимые функции, выполняющие действия, которые невозможно выполнить на уровне Си/Си++ кода или которые выполняют эти действия намного эффективнее. По сути, они позволяют избавиться от использования inline-ассемблера, так как его использование часто нежелательно или невозможно.

Программы могут использовать intrinsic-функции для создания более быстрого кода за счет отсутствия накладных расходов на вызов обычного вида функций. При этом, естественно, размер кода будет чуть-чуть больше. В MSDN приводится список функций, которые могут быть заменены их intrinsic-версией. Это, например, memcpy, strcmp и другие.

В компиляторе Microsoft Visual C++ есть специальная опция "/Oi", которая позволяет автоматически заменять вызовы некоторых функций на intrinsic-аналоги.

Помимо автоматической замены обычных функций на intrinsic-варианты, можно явно использовать в коде intrinsic-функции. Вот для чего это может быть нужно:

  • Как уже говорилось, встроенный (inline) ассемблерный код не поддерживается компилятором Visual C++ в 64-битном режиме. Intrinsic-код поддерживается.
  • Intrinsic-функции проще использовать, так как они не требуют знания регистров и других подобных низкоуровневых конструкций.
  • Intrinsic-функции обновляются в компиляторах. Ассемблерный же код придется обновлять вручную.
  • Встроенный оптимизатор не работает с ассемблерным кодом, поэтому требуется внешняя линковка модуля. Для intrinsic-кода такого не нужно.
  • Intrinsic-код легче переносить, чем ассемблерный.

Использование intrinsic-функций в автоматическом режиме (с помощью ключа компилятора) позволяет получить бесплатно несколько процентов прироста производительности, а "ручное" - даже больше. Поэтому использование intrinsic-функций вполне оправдано.

Более подробно с применением intrinsic-функций можно ознакомиться в блоге команды Visual C++.