Абсолютное значение двойного - PullRequest
0 голосов
/ 12 февраля 2010

Я пытаюсь написать функцию с именем absD, которая возвращает абсолютное значение своего аргумента. Я не хочу использовать какие-либо предопределенные функции. Прямо сейчас я получаю ошибку разбора, когда пытаюсь скомпилировать ее.

Я бы изобразил все, что мне нужно сделать, чтобы получить абсолютное значение типа double, это изменить бит знака? это то, что у меня есть

#include <stdio.h>
#include <stdlib.h>

#define PRECISION   3

double absD (double n)
{

asm("   fld     %eax \n"  
    "   movl    $0x7FFFFFFFFFFFFFFF,  %eax    \n"    
    "   pop     %eax     \n"

    );

return n;


}

int main (int argc, char **argv)
{
double  n = 0.0;

printf("Absolute value\n");
if (argc > 1)
    n = atof(argv[1]);

printf("abs(%.*f) = %.*f\n", PRECISION, n, PRECISION, absD(n));

return 0;
}

Я исправил фигурную скобку .. я получаю ошибку

~ $ gc a02
gcc -Wall -g a02.c -o a02
/tmp/ccl2H7rf.s: Assembler messages:
/tmp/ccl2H7rf.s:228: Error: suffix or operands invalid for `fld'
/tmp/ccl2H7rf.s:229: Error: missing or invalid immediate expression `0x7FFFFFFFF
FFFFFFF'
~ $

Ответы [ 7 ]

1 голос
/ 12 февраля 2010

Знак числа с плавающим битом - это только старший бит, поэтому все, что вам нужно, это очистить самый старший бит.

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

Кроме того, нет необходимости загружать все 8-байтовое значение в любой регистр, вы также можете легко работать только с старшим байтом (или int), если ваш процессор не имеет 8-байтовых целочисленных регистров. 1005 *

1 голос
/ 12 февраля 2010

В вашем ассемблерном коде есть ошибки, о которых ассемблер выдает совершенно разумные сообщения об ошибках.

  • вы не можете загрузить значение с плавающей точкой напрямую из% eax - операндом должен быть адрес для загрузки из

  • у вас не может быть константных литералов, которые не помещаются в 32 бита.

1 голос
/ 12 февраля 2010

В зависимости от того, как вы хотите обработать -0.0, вы можете использовать функцию signbit() C99 / POSIX (2004).

#include <math.h>

double absD (double x)
{
     if ( signbit(x) ) {
#ifdef NAIVE
         return 0.0 - x;
#else
         return x &= 0x7FFFFFFFFFFFFFFF;
#endif
     } else {
         return x;
     }
}

Но, честно говоря, если вы используете стандартную библиотеку C (libc) atof и printf, я не понимаю, почему не желательно fabs(). Как вы можете также сделать обычное бит-тиддлинг в C.

Конечно, если вы используете сборку, почему бы вообще не использовать fchs op?

1 голос
/ 12 февраля 2010
asm("   fld     %eax \n"  
"   movl    $0x7FFFFFFFFFFFFFFF,  %eax    \n"    
"   pop     %eax     \n"

};

обратите внимание на скобу кавычек перед точкой с запятой.

1 голос
/ 12 февраля 2010

Я не эксперт, но похоже, что вы используете (, чтобы открыть блок сборки, и }, чтобы завершить его. Вы, вероятно, должны использовать один или другой, а не оба непоследовательно.

1 голос
/ 12 февраля 2010

Нужно ли это делать в сборке? Это домашнее задание или вы ищете очень высокую производительность?

Это не использует предопределенные функции:

double absD(double n)
{
    if (n < 0.0)
        n = -n;

    return n;
}
0 голосов
/ 13 февраля 2010

/ tmp / ccl2H7rf.s: 228: ошибка: суффикс или недопустимые операнды для `fld '

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

/ tmp / ccl2H7rf.s: 229: ошибка: отсутствует или недопустимое немедленное выражение `0x7FFFFFFFF FFFFFFF '

EAX не содержит более 32 бит. Если вы хотели, чтобы это было число с плавающей запятой, поместите его в стек с плавающей запятой с помощью инструкции загрузки, то есть fld.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...