Преобразуйте этот встроенный ассемблерный код в работу с gcc.

Я пытаюсь преобразовать этот кусок кода для работы со сборкой AT&T, которую использует g++:

double sqrt13(double n)
{
__asm{
 fld n
 fsqrt
 }
}

На основании этой ссылки: https://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html: я пробовал это:

double raiz (double n)
    __asm__ ( "fld n\n\t"
    "fsqrt\n\t" );

но я продолжаю получать:

/tmp/cc2AQhHj.s|662|Error: junk `n' after expression|

То же сообщение об ошибке происходит еще четыре раза в других строках этого файла

Я скачал программу под названием "intel2gas", и он сказал мне, что код должен быть таким:

    __asm__ volatile__ (
    "fld %0\n"
    "fsqrt\n"
    :"=m"(n)
    :
    :"memory", "esi", "edi", "eax", "ebx", "ecx", "edx"
    );

помещая его внутрь функции и пытаясь запустить его, я получаю:

 |39|error: expected ‘(’ before ‘volatile__’|
|42|error: expected ‘)’ before ‘:’ token|
|45|error: ‘volatile__’ was not declared in this scope|

плюс |46| предупреждение: нет возврата в функции, возвращающей не void |

Итак, есть предложения?

1 ответ

intel2gas по-видимому, не реализует поддержку MSVC для того, чтобы оставить возвращаемое значение в EAX (или ST0) в asm и затем упасть с конца неvoid функция. MSVC рассматривает это как фактическое возвращаемое значение, даже когда встраивает функцию, содержащую __asm блок. В встроенном ассемблере GNU C значения регистров являются выходными, только если вы используете ограничения вывода или чтения / записи.

Вот почему вы получаете warning: no return statement in function returning non-void и неработающий код.

Как указывает @MichaelPetch, вы должны запросить у компилятора уже введенный номер плавающего указателя в стеке регистров x87 FP, используя t ограничение (вершина стека x87).

double raiz (double n) {
    __asm__ ("fsqrt"
       : "+t"(n)          // read-write operand: top of x87 stack
    );
     return n;
}

asm volatile не требуется: в блоке asm нет побочных эффектов, которые нужно запускать, даже если вывод не используется, а вывод является чистой функцией ввода. (Если вы не меняете режим округления x87 или точность).

Можно позволить компилятору оптимизировать его или CSE между несколькими запусками.

Как отдельная функция, это компилирует ( на Godbolt) в

# gcc8.2 -O3 -ffast-math -m32   uses x87 by default, not SSE2
_Z4raizd:
    fld     QWORD PTR [esp+4]
   # start of inline asm
    fsqrt
   # end of inline asm.
    ret
Другие вопросы по тегам