Преобразуйте этот встроенный ассемблерный код в работу с 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