2009-04-13 11 views
2

Je travaille sur un programme qui produit du code assembleur à partir d'expressions. L'une des fonctions requises est tan (x) qui travaille actuellement en utilisant la séquence de code suivante (les adresses sont remplies au moment de l'exécution):Pourquoi printf affiche -1. # IND pour les résultats FPTAN?

fld [0x00C01288]; 
fld st(0); 
fsin; 
fld st(1); 
fcos; 
fdivp; 
fst [0x0030FA8C]; 

Cependant, je voudrais utiliser le FPTAN opcode à la place, donc J'ai essayé en utilisant le code suivant:

fld [0x00C01288]; 
fptan; 
fincstp; 
fst [0x0030FA8C]; 

le programme de test utilise printf pour afficher le résultat stocké à 0x30FA8C, mais pour la deuxième séquence le résultat est affiché comme -1 # IND (la première utilisation de cos et des œuvres de péché. bien). Si j'essaie d'examiner la valeur à l'adresse mémoire, ou au-dessus de la pile à virgule flottante, dans le débogueur, il apparaît comme le nombre correct. Donc, ma question est: Pourquoi printf montre -1. # IND et comment puis-je le réparer?

La valeur à 0x00C01288 est double précision 0,5 Le résultat dans les deux cas est ~ 0,5463024898

Ma première pensée était que la valeur stockée est une représentation différente du même nombre, mais inspectant la valeur stockée à 0x0030FA8C montre qu'il s'agit de 0x3FE17B4F5BF3474A dans les deux cas.

Je ne comprends pas pourquoi les entrées identiques à la fonction printf pourrait produire une sortie différente ...

Toute aide ou suggestions seraient grandement appréciés.

Edit: Source où printf est appelé:

#include "FridgeScript.h" 
#include <stdio.h> 
#include <math.h> 

char test[] = "a=tan(0.5);"; 

int main(int c, char** s) 
{ 
    unsigned int SC = FSCreateContext(); 

    double a = 0.0; 
    FSRegisterVariable(SC, "a", &a); 

    unsigned int CH = FSCompile(SC, test); 
    if(CH) FSExecute(SC, CH); 

    printf("a: %.10g\r\n", a); 
    printf("hex a: %I64X", a); 

    FSDestroyContext(SC); 
    return 0; 
} 
+0

Pouvez-vous afficher le code source qui utilise la fonction printf? – veefu

+0

il y a beaucoup d'autres choses qui se passent ... mais je vais l'ajouter quand même. – jheriko

+1

"-1. # IND" est la façon de printf de dire NaN. Je n'ai pas d'autre aide à ajouter, mais cela pourrait être un peu utile de trivia ... – RBerteig

Répondre

9

Permettez-moi de jeter quelque chose là-bas: comment sur l'utilisation

fstp st(0); 

au lieu de

fincstp; 

Les docs sur fincstp dire que ce n'est pas équivalent à sauter l'élément de la pile, car il laisse cet endroit étiqueté comme rempli - peut-être c'est gâcher la manipulation de flotteur à l'intérieur de printf?

(Vous pouvez être en mesure de deviner, je ne sais pas ce que je parle. Mais peut-être cela vous donnera une idée?)

+0

Cela l'a parfaitement corrigé. Merci. Je suppose que va_args s'appuie sur la pile flottante avec la convention d'appel de printf ou quelque chose comme ça ... – jheriko

+0

Normalement printf() utilise la pile pour les paramètres, et peut-être certains registres sur x86-64. Il sait combien de paramètres rechercher en analysant la chaîne de format. IMO le problème se produisait lorsque printf() essayait d'utiliser FPU. –

+0

C'est une bonne idée pour quelqu'un qui ne sait pas de quoi ils parlent :-) +1 pour une bonne estimation. – paxdiablo

1
fld [0x00C01288]; 
fptan; 
fincstp; 
fst [0x0030FA8C]; 

Pour moi, il ressemble après exécution de ce code, la tangente est toujours à st0. Ne devriez-vous pas utiliser fstp au lieu de fst?

+0

Cela semble également lié à ma réponse. La pile fp contient encore des choses. –

+0

fst devrait le stocker à 0x0030FA8C, et le débogueur montre qu'il est bien écrit là. Puisque st (0) est utilisé pour les valeurs de retour, il doit également être laissé là pour que les expressions puissent être, par ex. "a = b = tan (0,5);" – jheriko

0

Peut-être votre instruction FST stocke-t-elle uniquement le résultat flottant et le second dword n'est toujours pas initialisé?

Je ne vois aucun préfixe de taille dans le code d'assemblage. Habituellement, vous voyez quelque chose comme:

FST [dword ptr some_address] 

    or 

    FS [qword ptr some_address]