C Встроенная сборка - несоответствие типов операндов для 'fst' - PullRequest
2 голосов
/ 05 января 2012

Привет, я пытаюсь научиться писать ассемблерный код в моих программах на Си. Я понимаю целые числа в сборке, но поплавки продолжают сбивать меня с толку.

double asmSqrt(double x) {
    double o;
    __asm__ ("fld %1;"
             "fsqrt;"
             "fst %0;"
             : "=g" (o)
             : "g"  (x)
    );
    return o;
}

Как видите, я просто пытаюсь найти квадратный корень из x. Но всякий раз, когда я пытаюсь его скомпилировать, я получаю ошибку несоответствия типов операндов.

Я следовал тому же синтаксису, что и здесь: http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx?display=Print

PS: я использую MinGW GCC в Windows XP

Ответы [ 4 ]

3 голосов
/ 05 января 2012

Вам необходимо явно указать, какие fld и fst варианты команд вы хотите. В противном случае компилятор не знает, каким должен быть ваш операнд. Этот код работает для меня здесь:

__asm__ ("fldl %1  ;"
         "fsqrt    ;"
         "fstl %0  ;"
         : "=g" (o)
         : "g"  (x)
);

Вы можете использовать дизассемблер, чтобы перепроверить, что правильные коды операций для 64-битных FLD и FST (DD/0 и DD/2) генерируются.

1 голос
/ 05 января 2012

Во-первых, почему ты это делаешь? Компилятор может делать квадратные корни сам. Вы просто вызываете правильную функцию математической библиотеки, включаете оптимизацию (чтобы она встроила стандартные функции), и я был бы удивлен, если бы она не выполняла то, что вы хотите. Результат - независимость от платформы (т. Е. Вы можете создать 64-битную, если хотите, или даже другую архитектуру), простой в обслуживании код - намного лучше!

Если вы настаиваете на том, чтобы сделать это трудным путем, gcc также может помочь здесь (я на самом деле не проверял это):

double asmSqrt(double x) {
  __asm__ ("fsqrt" : "+t" (x));
  return x;
}

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

Редактировать: О, и если вы делаете сами хотите внести изменения в регистры, вам лучше сообщить об этом компилятору в разделе 'clobbers', или вы можете перезаписать что-то, что он там хранил. 1012 *

0 голосов
/ 01 апреля 2013

double sqrt1 (double n) { __как м{ пол н fsqrt } }

вызов метода: двойной результат = sqrt1 ((double) 10), например

0 голосов
/ 05 января 2012

Укажите ячейку памяти "= m" вместо "= g". Но лучше всего прочитать это руководство здесь: http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s4

В любом случае, вот решение:

double asmSqrt(double x) {
  double o;
  __asm__ ("fld %1;"
           "fsqrt;"
           "fst %0;"
           : "=m" (o)
           : "g" (x)
  );
  return o;
}
...