IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

Optimisation multiplication complexe : problème de retour de valeur en double


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 52
    Points
    52
    Par défaut Optimisation multiplication complexe : problème de retour de valeur en double
    Bonjour,

    je tente d'optimiser le calcul d'un produit de 2 nombres complexes.
    en float pas de problème, c'est le retour de la valeur en double que je n'arrive pas à récupérer.

    OS : XP
    IDE : Visual studio 2005

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    __declspec(naked) int __fastcall pscald(double *x, double *y)
    {
            movddup		xmm0, [ecx*8]		; b, b(high , low qword of xmm0)
    	movapd		xmm1, [edx+16]		; d, c
    	mulpd		xmm0, xmm1		  ; bd, bc
    	shufpd		xmm1, xmm1, 1		 ; c, d
    	movddup		xmm2, [ecx]		 ; a,a
    	mulpd		xmm2, xmm1		  ; ac, ad
    	addsubpd	xmm0, xmm2		; ac+bd, ad –bc (the final result )
    	movapd		xmm3, xmm0;
     
            movlpd		eax, xmm3;
    	fld qword ptr[eax];
     
           ret 0
    }
    Ca me retourne 0 ou 1 dans le meilleur des cas....

  2. #2
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Je ne comprends pas la première instruction, ça ne devrait pas être quelque chose comme [ecx+8] (mais là on sort du double pointé par ECX) ?
    :wq

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 52
    Points
    52
    Par défaut
    Effectivement c'est bien [ecx+8].

    Ce qui par ailleurs était bien écrit dans mon projet

    En y réfléchissant, en épilogue de ma fonction, est-ce que je ne devrais pas copier le double 64bits qui m'intéresse dans [ebx] plutôt que dans [eax]. Et prévenir ensuite que [eax] doit être lu comme une qword ?

  4. #4
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Lea,
    Citation Envoyé par Antonin08 Voir le message
    ...
    Ce qui par ailleurs était bien écrit dans mon projet...
    Tu sais ce qu'est copier/coller ?
    Si les cons volaient, il ferait nuit à midi.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 52
    Points
    52
    Par défaut
    oui oui ... merci pour le conseil droggo je n'y avais pas pensé...

    J'ai en effet sélectionné la partie du code qui me semblait la plus pertinente pour ce post, d'où l'erreur

  6. #6
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Citation Envoyé par Antonin08 Voir le message
    En y réfléchissant, en épilogue de ma fonction, est-ce que je ne devrais pas copier le double 64bits qui m'intéresse dans [ebx] plutôt que dans [eax]. Et prévenir ensuite que [eax] doit être lu comme une qword ?
    L'int retourné doit se trouver dans EAX. Après je ne sais pas trop t'aider parce que je connais juste MMX et je n'ai pas vraiment compris ce que tu fais. x et y pointent tous les deux vers des nombres complexes ? Comment est-ce qu'on obtient la partie réelle et la partie imaginaire ?
    :wq

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 52
    Points
    52
    Par défaut On reprend du début

    En me relisant j 'ai plutôt été avare de détails. Comme j'ai la tête dedans, je pense que tout le monde est dans mon cas

    Je vais détailler un petit peu plus mon problème avec un début de réponse en plus...

    Objectif : Obtenir le module carré d'un produit scalaire complexe
    entrées : 2 complexes X et Y
    sortie : le scalaire calculé

    D'abord le code initial en float:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
     
    extern int __fastcall mod2(float *X, float *Y);
     
    __declspec(naked) int __fastcall mod2(float *X, float *Y)
    {
     
    __asm {
     
        ; fascall Microsoft => arg1 dans ECX, arg2 dans EDX  
        movshdup   xmm0,[ecx]		; multiplier imag (b1, b1, b0, b0)
        movaps     xmm1,[edx]		; multiplicand (d1, c1, d0, c0)      
        mulps      xmm0, xmm1		; temp1 (b1d1, b1c1, b0d0, b0c0)
        shufps     xmm1, xmm1, 0xb1         ; shuf multiplicand(c1, d1, c0, d0)
        movsldup   xmm2,[ecx]		; multiplier real  (a1, a1,a0, a0 )       
        mulps      xmm2, xmm1		; temp2 (a1c1, a1d1, a0c0, a0d0)
        addsubps   xmm2, xmm0		; a1c1+b1d1, a1d1-b1c1, a0c0+b0d0, a0d0-b0c0
        movaps     xmm3, xmm2;
     
    ; fascall Microsoft => valeur retour dans EAX si declaration en
     
    	movd       eax, xmm3;
    	ret;
    }
     
    typdedef struct _CPLX
    {
    float r;
    float i;
    } complexe;
    int main(void) 
    {
    <div style="margin-left:40px">
    complexe X,Y;
    float module2;
     
    ...
     
    *(int*) &module2 = mod2((float*) &X, (float*) &Y);
     
    ...
     
     
     
    return 0;</div>}
    On remarquera la syntaxe un peu spécial du retour de mod2

    J'ai donc tenté la même chose en double, ce qui n'a pas du tout fonctionné. Ca compile, ça execute mais ca ne renvoie pas la valeur attendue.

    J'ai donc opté pour un code plus simple pour le moment où j'ai enlevé la macro __declspec(naked)

    Code en double
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    extern double__fastcall mod2(double *X, double *Y);
     
    double__fastcall mod2(double *X, double *Y)
    {
     
    <div style="margin-left:40px">double xx;
     
    __asm {
     
            movddup		xmm0, [ecx+8]		; b, b(high , low qword of xmm0)
    	movapd		xmm1, [edx+16]		; d, c
    	mulpd		xmm0, xmm1		  ; bd, bc
    	shufpd		xmm1, xmm1, 1		 ; c, d
    	movddup		xmm2, [ecx]		 ; a,a
    	mulpd		xmm2, xmm1		  ; ac, ad
    	addsubpd	xmm0, xmm2		; ac+bd, ad –bc (the final result )
    	movapd		xmm3, xmm0;
     
            mulpd       xmm3, xmm3;       xmm3=<zr*zr zi*zi>
            haddpd      xmm3, xmm3;        xmm3=<N2  N2>  */
     
    	movlpd	 qword ptr [xx], xmm3;
    	fld	 qword ptr [xx];
    }</div>}
     
    int main(void)
    {<div style="margin-left:40px">
    complexeD X,Y,
    double module2;
     
    ...
     
    module2 = mod2((double*) &X, (double*) &Y);
     
    ...
     
    return 0;</div>}
    Ceci marche parfaitement

    Mais à quoi sert __declspec(naked) :

    Cette macro permet la suppression du prolog et de l'epilog, respectivement sauvegarde et restauration du contexte.
    Comme j'ai l'intention vous vous en doutez de faire du calcul intensif sur cette fonction et que le contexte dans cette optique n'est pas utilisé, alors autant ce passer des quelques instructions de contexte qui "ne servent à rien".

    Remarque en passant sur le calcul initial en float pour ceux qui ont suivi que j'ai déjà commencé à faire 2 produits scalaire simultannément

    Voilà je suis donc dans l'impasse pour récupérer ma valeur en double en utilisant la macro __declspec(naked) int car le retour se fait sur un type int. J'avais déjà changé de type pour du float sans succès. Le compilateur n'aime pas trop.

    donc comment récupérer un double dans une variable de retour sur 32bit ? en même temps il s'agit de récupérer une adresse ...

    A suivre...

  8. #8
    Membre confirmé Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Points : 567
    Points
    567
    Par défaut
    Je ne comprends pas pourquoi tu fais passer les adresses de tes complexes pour des adresses de float ou double, au niveau du code assembleur ça ne change rien et ça t'oblige à faire des casts en C.
    Sinon pour le reste je ne peux pas t'aider.
    :wq

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 52
    Points
    52
    Par défaut
    C'est l'habitude que j'ai prise quand je passe des pointeurs qui ne sont pas du type attendu par la fonction. Ca évite de voir le compilateur émettre des warnings. Je sais comme cela que c'est fait de façon intentionnelle.

    Effectivement au niveau assembleur ça ne change rien...
    merci


    Sinon je vais arrêter le post et le considérer comme résolu. Je vais me contenter de ce que j'ai déjà.

    Merci à tout ceux qui ont pris le temps de lire, de comprendre et ceux qui ont essayé d'apporter une réponse....
    une pensée spéciale pour droggo

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Problème de recherche de valeur sur variable multiple
    Par Vinces007 dans le forum C#
    Réponses: 7
    Dernier message: 02/08/2013, 09h08
  2. [MySQL] Problème: Mauvais retour de valeur dans mysql
    Par Krabbos dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 27/05/2011, 15h09
  3. Réponses: 23
    Dernier message: 28/05/2008, 17h53
  4. Problème de récupération de valeur d'un select multiple
    Par poissonsoluble dans le forum Balisage (X)HTML et validation W3C
    Réponses: 6
    Dernier message: 30/11/2006, 09h37
  5. [SQL] Problème de récupération des valeurs d'une liste multiple en php
    Par BOLARD dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 01/05/2006, 00h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo