Je commence juste à apprendre l'assemblage et je veux arrondir une valeur à virgule flottante en utilisant un mode d'arrondi spécifié. J'ai essayé de l'implémenter en utilisant fstcw
, fldcw
et frndint
.nombres double précision dans l'assemblage en ligne (GCC, IA-32)
En ce moment, je reçois quelques erreurs:
~ $ gc a02p
gcc -Wall -g a02p.c -o a02p
a02p.c: In function `roundD':
a02p.c:33: error: parse error before '[' token
a02p.c:21: warning: unused variable `mode'
~ $
Je ne sais pas si je suis en train de faire, même ce droit à tout. Je ne veux utiliser aucune fonction prédéfinie. Je veux utiliser l'assemblage en ligne GCC.
Voici le code:
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
#define RND_CTL_BIT_SHIFT 10
// floating point rounding modes: IA-32 Manual, Vol. 1, p. 4-20
typedef enum {
ROUND_NEAREST_EVEN = 0 << RND_CTL_BIT_SHIFT,
ROUND_MINUS_INF = 1 << RND_CTL_BIT_SHIFT,
ROUND_PLUS_INF = 2 << RND_CTL_BIT_SHIFT,
ROUND_TOWARD_ZERO = 3 << RND_CTL_BIT_SHIFT
} RoundingMode;
double roundD (double n, RoundingMode roundingMode)
{
short c;
short mode = ((c & 0xf3ff) | (roundingMode));
asm("fldcw %[nIn] \n"
"fstcw %%eax \n" // not sure why i would need to store the CW
"fldcw %[modeIn] \n"
"frndint \n"
"fistp %[nOut] \n"
: [nOut] "=m" (n)
: [nIn] "m" (n)
: [modeIn] "m" (mode)
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
if (argc > 1)
n = atof(argv[1]);
printf("roundD even %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_NEAREST_EVEN));
printf("roundD down %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_MINUS_INF));
printf("roundD up %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_PLUS_INF));
printf("roundD zero %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_TOWARD_ZERO));
return 0;
}
Suis-je même de loin pour obtenir ce droit?
Un de vos camarades de classe a déjà demandé cela. http://stackoverflow.com/questions/2249917/working-with-double-precision-numbers-in-inline-assembly-gcc-ia-32 – martinwguy
Il ne sert à rien d'utiliser 'fstcw' juste après avoir heurté l'ancien mot de contrôle avec 'fldcw' avec une constante. Vous ne chargez jamais 'n' dans le FPU x87. Inline asm est une façon horrible de le faire, donc je ne vais pas prendre le temps d'écrire une réponse complète. Utilisez simplement 'lrint (n)' ou quelque chose. –