2014-12-28 3 views
3

Я пытаюсь переписать этот фрагмент кода для работы в Visual Studio, но я явно не понимаю, как использовать цель двоеточия и значение __volatile__,Преобразование GCC/ATT в ассемблер на ассемблер визуальной студии?

может предложить вам некоторую помощь :)?

__asm__ __volatile__ (
    "mov %0, %%edi\n" 
    "xor %%eax, %%eax\n" 
    "xor %%ecx, %%ecx\n" 
    "dec %%ecx\n" 
    "repne scasb\n" 
    "sub %%ecx, %%eax\n" 
    "dec %%eax\n" 
: 
: "m" (src) 
: "memory", "%ecx", "%edi", "%eax"); 

Спасибо!

+0

[Первый удар по Google] (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html). Вы в основном просите нас обобщить эту страницу? – Columbo

+0

Нет, я пробовал самостоятельно несколькими способами, но не смог добиться успеха, поэтому я разместил здесь оригинальный код. – user1326293

+1

Это похоже на 'strlen()' или подобное. Почему вы беспокоитесь и не используете обычный цикл или подходящую существующую замену? – wilx

ответ

2

Два встроенных ассемблера совершенно разные. Встраиваемый ассемблер Visual Studio более примитивен, но проще в использовании. В VS:

  • встроенный язык сборки не обязательно должен быть заключен в строку;
  • операнды инструкции находятся в dest, src order;
  • Переменные C/C++ доступны как есть;
  • т.д.

Ваш код не имеет каких-либо выходных операторов (после первого двоеточия), так что я не вижу, как это может иметь какой-либо эффект. Но предположим, что регистр eax должен быть сохранен в переменной src в конце. Тогда вы хотите что-то вроде этого:

char* src; 
... 
__asm { 
    mov edi,src 
    xor eax,eax 
    xor ecx,ecx 
    dec ecx 
    repne scasb 
    sub eax,ecx 
    dec eax 

    mov src,eax // save result 
} 

Кстати, для меня это выглядит неоптимально. Все, что бизнес с eax может быть сделано not ecx, если я понимаю, код правильно:

__asm { 
    mov edi,src 
    xor al,al 
    xor ecx,ecx 
    dec ecx 
    repne scasb 
    not ecx 

    mov src,ecx // save result 
} 
+0

Почему вы отменили XOR EAX, EAX? –

+0

@ user3144770: Почему, по-вашему, это необходимо? – TonyK

+1

Инструкция SCASB использует регистр AL. Итак, почему он не должен быть правильно инициализирован? –

0

... Я не понимаю ... цель двоеточиями ...

Как отметил Коломбо в своем комментарии, вот соответствующая страница руководства: 6.43.2 Extended Asm - Assembler Instructions with C Expression Operands. Двоеточия просто разделяют токены в блоке ASM. Они похожи на точку с запятой, завершающую инструкцию C (или, вернее, оператор запятой, поскольку они связаны).

И повторить то, что страница говорит, общий формат:

asm (
     Instructions (Assembler Code) 
     : Outputs (C variables modified by the instructions) 
     : Inputs (C expressions read by the instructions) 
     : Clobbers (Registers or other values changed by the instructions) 
    ) 

Иногда не будет никаких маркеров между точкой с запятой. Например, вот что барьер памяти выглядит следующим образом:

__asm__ __volatile__ ("" ::: "memory") 

Там нет кода на ассемблере, нет никаких C переменные, используемые в качестве вывода, и нет никаких C выражений, используемых в качестве входных данных. Но память указана как сбитая, поэтому компилятор знает, что ожидающие завершения чтения и записи были выполнены до того, как будет выполнена следующая инструкция.


... Я не понимаю ... смысл __volatile__

ОК, так что это может червей, потому что GCC и Visual Studio интерпретировать смысл volatile по-разному (даже если они используют ту же спецификацию языка C).

В GCC единственная причина использования volatile - это когда аппаратное обеспечение может менять память. Поэтому я считаю, что использование квалификатора volatile является злоупотреблением в приведенном выше примере (поскольку он выглядит так, как функция сканирует байт NULL и не выполняет операции ввода/вывода с отображением памяти).

Вы можете найти соответствующее обсуждение в списке рассылки GCC по адресу volatile shared memory. Ян Лэнс Тейлор, который предоставил ответ ниже, является одним из разработчиков GCC:

Нет, изменчивый не может решить эту проблему. Это не то, что для летучего . Летучий определитель предназначен для работы с аппаратным обеспечением памяти . Он не предназначен для многопроцессорной общей памяти . Если программа не является многопроцессорной, то добавление volatile никогда не сделает ее многопроцессорной.


EDIT: Как Тони указал ниже, volatile is used to tame the optimizer так, что блок ASM не удаляется во время компиляции.


Также обратите внимание, что вы можете преобразовать код встроенный ассемблер для x86, но вы не можете сделать это для x64. Microsoft не поддерживает встроенную сборку для x64. См. Intrinsics and Inline Assembly на MSDN.

+2

'volatile' необходим, чтобы остановить компилятор GCC от оптимизации всего asm-блока. В Visual Studio это не имеет никакого отношения, о котором никогда бы не хотелось этого делать. – TonyK

+0

@ Тони - это интересно. Я никогда не вспоминаю его чтение в документах GCC. У вас есть цитата? (Возможно, мне потребуется обновить этот ответ). – jww

+1

https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile. Это правда, что в большинстве случаев «volatile» не нужен, но если вам все равно, оптимизирован ли ваш asm-блок или нет, разумно использовать его по умолчанию. – TonyK

Смежные вопросы