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

Pascal Discussion :

Insertion d'assembleur dans une méthode d'objet


Sujet :

Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Billets dans le blog
    1
    Par défaut Insertion d'assembleur dans une méthode d'objet
    Bonjour,
    Je fais tourner un serveur sur lequel il peut y avoir plusieurs dizaines de joueurs de bridge en même temps.
    Cela plante de temps à autre et je soupçonne la fonction Pos d'être victime de collisions car je l'utilise abondamment.
    j'ai donc pensé mettre cette fonction comme méthode du joueur afin qu'il n'y ait que lui qui l'appelle.
    Du coup je suis allé chercher l'assembleur de Posex et j'ai créé une méthode posex en assembleur.
    Cela plante sur le retour de la fonction ( instruction asm ret)
    j'ai fait un test spécial dans un module de test et si j'appelle la fonction en assembleur directement cela marche sans problème, mais si elle est une méthode d'un objet cela plante sur le ret.
    Avez-vous une idée de ce qui ne va pas ?
    merci..

  2. #2
    Membre confirmé

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Billets dans le blog
    1
    Par défaut exemple de 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
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    Trequete=  class(Tobject)
      Public
      function PosEx2(const SubStr, S: string; Offset: Integer = 1): Integer;
    end;
     
    var
      Form1: TForm1;
      Requete: Trequete;
    implementation
     
    {$R *.dfm}
     
    function PosEx1(const SubStr, S: string; Offset: Integer = 1): Integer;
    asm
           test  eax, eax
           jz    @Nil
           test  edx, edx
           jz    @Nil
           dec   ecx
           jl    @Nil
     
           push  esi
           push  ebx
     
           mov   esi, [edx-4]  //Length(Str)
           mov   ebx, [eax-4]  //Length(Substr)
           sub   esi, ecx      //effective length of Str
           add   edx, ecx      //addr of the first char at starting position
           cmp   esi, ebx
           jl    @Past         //jump if EffectiveLength(Str)<Length(Substr)
           test  ebx, ebx
           jle   @Past         //jump if Length(Substr)<=0
     
           add   esp, -12
           add   ebx, -1       //Length(Substr)-1
           add   esi, edx      //addr of the terminator
           add   edx, ebx      //addr of the last char at starting position
           mov   [esp+8], esi  //save addr of the terminator
           add   eax, ebx      //addr of the last char of Substr
           sub   ecx, edx      //-@Str[Length(Substr)]
           neg   ebx           //-(Length(Substr)-1)
           mov   [esp+4], ecx  //save -@Str[Length(Substr)]
           mov   [esp], ebx    //save -(Length(Substr)-1)
           movzx ecx, byte ptr [eax] //the last char of Substr
     
    @Loop:
           cmp   cl, [edx]
           jz    @Test0
    @AfterTest0:
           cmp   cl, [edx+1]
           jz    @TestT
    @AfterTestT:
           add   edx, 4
           cmp   edx, [esp+8]
           jb   @Continue
    @EndLoop:
           add   edx, -2
           cmp   edx, [esp+8]
           jb    @Loop
    @Exit:
           add   esp, 12
    @Past:
           pop   ebx
           pop   esi
    @Nil:
           xor   eax, eax
           ret
    @Continue:
           cmp   cl, [edx-2]
           jz    @Test2
           cmp   cl, [edx-1]
           jnz   @Loop
    @Test1:
           add   edx,  1
    @Test2:
           add   edx, -2
    @Test0:
           add   edx, -1
    @TestT:
           mov   esi, [esp]
           test  esi, esi
           jz    @Found
    @String:
           movzx ebx, word ptr [esi+eax]
           cmp   bx, word ptr [esi+edx+1]
           jnz   @AfterTestT
           cmp   esi, -2
           jge   @Found
           movzx ebx, word ptr [esi+eax+2]
           cmp   bx, word ptr [esi+edx+3]
           jnz   @AfterTestT
           add   esi, 4
           jl    @String
    @Found:
           mov   eax, [esp+4]
           add   edx, 2
     
           cmp   edx, [esp+8]
           ja    @Exit
     
           add   esp, 12
           add   eax, edx
           pop   ebx
           pop   esi
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    Var
    S: String;
     
    begin
      Requete:= Trequete.Create;
      S:='Je vous adresse une requête';
      //test direct
      if Posex1('Requête',S)>0 then showMessage('OK') else showMessage('pas OK');
      if Posex1('requête',S)>0 then showMessage('OK') else showMessage('pas OK');
     
      //test de la méthode
      if requete.Posex2('Requête',S)>0 then showMessage('OK') else showMessage('pas OK');
      if requete.Posex2('requête',S)>0 then showMessage('OK') else showMessage('pas OK');
     
    end;
     
    function Trequete.PosEx2(const SubStr, S: string; Offset: Integer = 1): Integer;
    asm
           test  eax, eax
           jz    @Nil
           test  edx, edx
           jz    @Nil
           dec   ecx
           jl    @Nil
     
           push  esi
           push  ebx
     
           mov   esi, [edx-4]  //Length(Str)
           mov   ebx, [eax-4]  //Length(Substr)
           sub   esi, ecx      //effective length of Str
           add   edx, ecx      //addr of the first char at starting position
           cmp   esi, ebx
           jl    @Past         //jump if EffectiveLength(Str)<Length(Substr)
           test  ebx, ebx
           jle   @Past         //jump if Length(Substr)<=0
     
           add   esp, -12
           add   ebx, -1       //Length(Substr)-1
           add   esi, edx      //addr of the terminator
           add   edx, ebx      //addr of the last char at starting position
           mov   [esp+8], esi  //save addr of the terminator
           add   eax, ebx      //addr of the last char of Substr
           sub   ecx, edx      //-@Str[Length(Substr)]
           neg   ebx           //-(Length(Substr)-1)
           mov   [esp+4], ecx  //save -@Str[Length(Substr)]
           mov   [esp], ebx    //save -(Length(Substr)-1)
           movzx ecx, byte ptr [eax] //the last char of Substr
     
    @Loop:
           cmp   cl, [edx]
           jz    @Test0
    @AfterTest0:
           cmp   cl, [edx+1]
           jz    @TestT
    @AfterTestT:
           add   edx, 4
           cmp   edx, [esp+8]
           jb   @Continue
    @EndLoop:
           add   edx, -2
           cmp   edx, [esp+8]
           jb    @Loop
    @Exit:
           add   esp, 12
    @Past:
           pop   ebx
           pop   esi
    @Nil:
           xor   eax, eax
           ret
    @Continue:
           cmp   cl, [edx-2]
           jz    @Test2
           cmp   cl, [edx-1]
           jnz   @Loop
    @Test1:
           add   edx,  1
    @Test2:
           add   edx, -2
    @Test0:
           add   edx, -1
    @TestT:
           mov   esi, [esp]
           test  esi, esi
           jz    @Found
    @String:
           movzx ebx, word ptr [esi+eax]
           cmp   bx, word ptr [esi+edx+1]
           jnz   @AfterTestT
           cmp   esi, -2
           jge   @Found
           movzx ebx, word ptr [esi+eax+2]
           cmp   bx, word ptr [esi+edx+3]
           jnz   @AfterTestT
           add   esi, 4
           jl    @String
    @Found:
           mov   eax, [esp+4]
           add   edx, 2
     
           cmp   edx, [esp+8]
           ja    @Exit
     
           add   esp, 12
           add   eax, edx
           pop   ebx
           pop   esi
    end;
     
    end.
    On voit que le premier marche, mais le second génère une erreur... pourquoi? et que faut-il faire pour que cela marche ,

  3. #3
    Membre émérite

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Par défaut
    Bonjour,

    Dans une méthode de classe il y a un paramètre caché suppémentaire qui est un pointeur sur l'instance de classe appelante (Self).
    Par conséquent pour les registres il faut considérer qu'elle est en fait déclarée comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function Trequete.PosEx2(  Self: Trequete;  const SubStr, S: string; Offset: Integer = 1): Integer;
    EAX n'est donc plus Substr mais Self. Ce qui permet d'accéder à tous les éléments de l'objet appelant.
    Cela décale d'autant l'allocation registre des autres paramètres.

  4. #4
    Membre confirmé

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Billets dans le blog
    1
    Par défaut
    Je crois comprendre que le code initial substr est pointé par eax, S par edx et que Offset par ecx ? Et que donc maintenant ils ne sont plus nécessairement dans ces registres là ?
    J'essaie de regarder en déboguant le contenu des registres dans les 2 cas. je vais voir si je comprends ce qu'il y a modifier dans le code. merci

  5. #5
    Membre émérite

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Par défaut
    Citation Envoyé par GerardJ Voir le message
    Je crois comprendre que le code initial substr est pointé par eax, S par edx et que Offset par ecx ? Et que donc maintenant ils ne sont plus nécessairement dans ces registres là ?
    Exact !

    Il devrait y avoir :
    EAX : Self
    EDX : Substr
    ECX : S
    et Offset redevient un paramètre Pascal normal placé sur la pile juste avant l'adresse de retour.

  6. #6
    Membre confirmé

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Billets dans le blog
    1
    Par défaut
    Donc si je comprends bien pour récupérer Offset il faut faire un Pop ce qui ramène l'adresse de retour en haut de la pile ?
    Et tel que c'est fait là, c'est en fait offset qui est interprété comme adresse de retour ? je comprends alors pourquoi cela plante sur l'instruction ret...
    j'ai un peu de temps je vais faire des essais ! merci !
    Bon alors, voici ce que j'ai fait et qui marche presque...
    Considérant que S est initialement dans Ecx, que je n'ai rien à cirer du self dans eax (?) et que le code commence par tester le contenu de eax, j'ai tout simplement implémenté ceci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    asm
           mov eax, ecx
           test  eax, eax
           jz    @Nil
           test  edx, edx
           jz    @Nil
           pop   ecx
           dec   ecx
           jl    @Nil
    Je mets ecx dans eax afin de le tester comme initialement, puis je mets la première variable de la pile dans ecx qui est testée...
    Tout cela devrait conduire à rétablir l'arrangement tel que la routine le teste !
    Et cela marche pour mon premier test j'ai bien le message 'pas OK' ce qui veut dire que les modifs ont fait ce qu'on attendait...

    Mais, mais, ...
    Pour le second test, j'ai un signalement d'erreur : instruction privilégiée...
    Le self que j'ai écrasé avait-il une importance ?

Discussions similaires

  1. Utiliser propriété de mon objet dans une méthode callback ?
    Par StringBuilder dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 19/11/2014, 10h08
  2. Passer une liste d'objets dans une méthode ajax
    Par AsPrO dans le forum ASP.NET Ajax
    Réponses: 4
    Dernier message: 01/03/2012, 11h28
  3. Appelle du destructeur dans une méthode du même Objet
    Par leo_OrNg dans le forum Débuter
    Réponses: 4
    Dernier message: 03/01/2010, 00h37
  4. [objet] appeler une méthode d'objets contenus dans un tableau (iterator ?)
    Par psychomatt dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 21/09/2006, 16h28
  5. Réponses: 2
    Dernier message: 15/11/2004, 15h12

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