2010-02-21 4 views
0

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?

+1

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

+0

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. –

Répondre

0

Un meilleur processus consiste à écrire une fonction simple qui arrondit une valeur en virgule flottante. Ensuite, demandez à votre compilateur d'imprimer une liste d'assemblage pour la fonction. Vous voudrez peut-être mettre la fonction dans un fichier séparé.

Ce processus affiche les conventions appelantes et sortantes utilisées par le compilateur. En plaçant la fonction dans un fichier séparé, vous n'aurez pas à créer d'autres fichiers. En outre, il vous donnera l'opportunité de remplacer la fonction de langage C par une fonction de langage d'assemblage. Bien que l'assemblage en ligne soit supporté, je préfère remplacer une fonction entière en langage assembleur et ne pas utiliser l'assemblage en ligne (l'assemblage en ligne n'est pas portable, donc la source devra être changée lors du portage vers une plate-forme différente).

0

La syntaxe de l'assembleur en ligne de GCC est pour le moins mystérieuse, et je ne prétends pas être un expert, mais quand je l'ai utilisé, j'ai utilisé this howto guide. Dans tous les exemples, tous les marqueurs de modèle sont de la forme% n, où n est un nombre, plutôt que la forme% [ttt] que vous avez utilisée.

Je remarque également que les numéros de ligne indiqués dans vos messages d'erreur ne semblent pas correspondre au code que vous avez publié. Donc je me demande s'ils sont en fait pour ce code exact?

+1

L'utilisation de '% [identifiant]' semble correcte. Cela rend le code plus lisible. Plutôt que '% #' vous pouvez utiliser l'identifiant. Les deux fonctionnent aussi bien, l'un est plus lisible. Un autre avantage est que vous pouvez réorganiser les contraintes et ne pas vous soucier de renuméroter toutes les références dans le modèle. –

Questions connexes