2012-01-05 2 views
2

Эй, я пытаюсь научиться писать код сборки в моих программах на C. Я понимаю целые числа в сборке, но поплавки продолжают меня трогать.C Встроенная сборка - несоответствие типа операнда для 'fst'

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

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

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

PS: Im используя MinGW GCC на Windows XP

+0

ли призвание соглашение о Windows возвращает float в регистр ST0 или FP0? – rsaxvc

+0

Каковы ваши флагов для компилятора? – rsaxvc

+0

Я думаю, что будет ненужно сброситься обратно в стек, чтобы избежать того, что вам нужно также реализовать возврат. Промывка стека также снижает вашу точность до 64-битного двойного вместо 80-бит x87. (Если вы делаете это для скорости, вам нужно больше, если для изучения, ответ Карла исправил его для меня). – rsaxvc

ответ

-2

Укажите ячейку памяти "= т" вместо "= г". Но лучше, чтобы прочитать это руководство здесь: 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; 
} 
+0

Не работает на моей машине ...он имеет ту же ошибку, что и ОП указывает на несоответствия типа операнда. На самом деле, поскольку я использую clang, он говорит: «Неоднозначные инструкции требуют явного суффикса (могут быть« flds »,« fldl »или« fldt »)». –

+0

Спасибо, но все еще проблема. Он компилируется и, кажется, отлично работает, но когда я распечатываю возвращаемое значение, его просто 0.0, и он также, похоже, делает фанки с любым кодом вокруг него. 'int main() { \t двойной номер = 5.12343; \t printf ("% f% f", number, asmSqrt (144.0)); \t getchar(); } ' Когда я запустил эту функцию, функция возвращает огромное длинное плавание. И спасибо за ссылку. Объяснил различные ограничения намного лучше, чем любой другой веб-сайт, который я видел до сих пор. Очень признателен. – Dan

+0

достаточно честный; примеры игрушек хороши для учебных целей. :) Я предлагаю вам выбрать соответствующее руководство из [здесь] (http://gcc.gnu.org/onlinedocs) и выполнить поиск в оглавлении для «ограничений» - ограничение 't' указано в части, относящейся к машине , Также есть раздел (как раз перед этим), в котором рассказывается об «asm» в общем и об использовании стека с плавающей запятой x86 в частности. – ams

3

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

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

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

+0

Я пробовал этот код, и он все еще не работает:/может это быть что-то с компилятором? – Dan

+0

Я уверен, что GCC смог обработать встроенную сборку довольно успешно в течение некоторого времени. У меня нет MinGW, поэтому, возможно, это связано с окружающей средой. Извините, этот ответ не помог! –

+0

Я скомпилировал выполненный на моей машине linux, и ваше решение отлично работало, поэтому должно быть что-то внутри MinGW, как вы сказали. Большое вам спасибо за вашу помощь! Редактировать: В окнах мне нужно было указать размер, как вы упоминали, и использовать ограничение памяти для o. Я не знаю, почему я не думал, чтобы попробовать это раньше :) Еще раз спасибо всем за то, что помогли мне! – Dan

1

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

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

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

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

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

+0

Цели обучения. У меня есть другой код сборки, в котором я использую код, который я разместил, и продолжаю эту ошибку. Я просто изолировал инструкцию fsqrt, потому что я могу заменить ее чем-то вроде idiv, и она отлично работает. Но спасибо за рабочий код – Dan

0

двойной sqrt1 (двойной п) { __asm ​​{ FLD п fsqrt } }

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