1. #1
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    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 du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    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 averti

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

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

    Informations forums :
    Inscription : octobre 2009
    Messages : 102
    Points : 433
    Points
    433

    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 du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    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 averti

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

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

    Informations forums :
    Inscription : octobre 2009
    Messages : 102
    Points : 433
    Points
    433

    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 du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    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 ?

  7. #7
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    Billets dans le blog
    1

    Par défaut

    Cela est sans doute le point car l'erreur apparait lors du second appel de la fonction...
    Nom : Assembleur.JPG
Affichages : 60
Taille : 51,7 Ko
    Il y a encore quelque chose qui m'échappe...mais c'est super de travailler cela avec vous !

  8. #8
    Membre expert
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2002
    Messages
    2 423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : mai 2002
    Messages : 2 423
    Points : 3 805
    Points
    3 805

    Par défaut

    salut

    as tu fait attention au processeur que tu utilise ?
    l'asm est différent selon le cas
    de plus si tu encadre la fonction par un begin et un end tu n'as plus a te soucier
    des push et pop de sortie si je me souvient bien

    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
     
    Function Trequete.PosEx2(const SubStr, S: string; Offset: Integer = 1): Integer;
    var
      Ivar : Integer
    Begin
    {$IFDEF PUREPASCAL}
      begin
        // Pascal implementé ici...
      end;
    {$ELSE !PUREPASCAL}
      {$IFDEF CPUX86}
        asm
           // Registre dispo
           // EAX, ECX, EDX,...
             MOV EDX, DWORD PTR SubStr;
             MOV ECX, DWORD PTR S;
            // ...
        end;
       {$ENDIF CPUX86}
       {$IFDEF CPUX64}
        asm
          // Registre dispo
          // RAX, RBX, RCX, RDX,...
          MOV RDX, SubStr {R8}
          MOV R8D, s {R9D}
          // ...
        end;
      {$ENDIF CPUX64}
    {$ENDIF !PUREPASCAL}
      Result := Ivar;
    end;
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #9
    Membre averti

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

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

    Informations forums :
    Inscription : octobre 2009
    Messages : 102
    Points : 433
    Points
    433

    Par défaut

    Bon c'est en bonne voie, malgré les apparences, mais il y a quelques petites choses qui doivent être précisées :

    1. Initialisation de EAX : en principe, pas de problème pour écraser Self dans le mesure ou vous n'avez pas besoin d'accéder aux autres éléments de l'objet (membres, propriétés ou méthodes). Mais c'est Substr qui devrait y être mis et non S.
    2. S qui est dans ECX devrait être transféré dans EDX.
    3. enfin la récupération d'Offset sur la pile ne peut en aucun cas être faite par un POP, surtout comme vous l'avez fait ! Celà mérite une petite explication :


    J'avait bien précisé que Offset était placé sur la pile AVANT l'adresse de retour. Cela signifie que la procédure appelante empile d'abord les paramètres (ceux qui ne sont pas transmis par registre) et fait ensuite un CALL à la méthode. C'est ce CALL qui empile l'adresse de retour par dessus le dernier paramètre.

    Le Pop ecx que vous avez écrit à donc pour effet de mettre cette adresse de retour dans ECX et surtout de l'enlever de la pile, avec les conséquences que l'on peut imaginer. C'est d'ailleurs surprenant qu'il n'y ai pas de crash dès le premier appel.

    De plus le compilateur, en présence de paramètres passés par la pile, met en place ce que l'on appelle un "cadre de pile" qui est un dispositif destiné à faciliter l'accès aux paramètres (ainsi qu'à la gestion des variables locales s'il y en a).

    Ce cadre de pile est mis en place par quelques instructions, insérée automatiquement par le compilateur, avant la première instruction du bloc asm. On appelle ces instructions "prologue" de la procédure. Dans notre cas, (absence de variables locales) c'est généralement quelque chose comme :
    Code ASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       Push EBP  // sauvegarde de ebp
       MOV  EBP, ESP
    EBP contient alors une copie du pointeur de pile à ce moment, copie non sujette a variations comme le serait ESP qui peut varier au gré des Push et des Pop. EBP sera utilisé comme base fixe pour indexer tout ce qui se trouve sur la pile, dont notamment les paramètres empilés par la routine appelante.
    Coup de chance vous n'utilisez pas ce regitre EBP dans votre procédure, nous allons donc pouvoir l'utiliser pour l'usage qui lui est réservé, a savoir récupérer le paramètre Offset :
    Code ASM : Sélectionner tout - Visualiser dans une fenêtre à part
       MOV  ECX, [EBP+8]  // Offset -> ECX
    Pourquoi +8 ? Et bien tout simplement pour sauter par dessus la sauvegarde de EBP (4 octets) et de l'adresse retour (encore 4 octets). Le calcul est ici facile mais peut l'être un peu moins s'il y a beaucoup de paramètres. Aussi il est possible de le faire faire par le compilateur lui-même en exprimant l'instruction ainsi :
    Le nom Pascal du paramètre est utilisé par le compilateur pour développer l'argument d'adressage qui permet d'atteindre le-dit paramètre. Remarquez le signe & placé devant Offset, celui-ci est nécessaire parce-que "Offset" est aussi un mot réservé du langage assembleur, sans ce signe on aurait une erreur de syntaxe.

    Cette possibilité peut aussi être utilisée pour les paramètres passés par registe.
    Par exemple le code pourrait donc commencer comme suit :
    Code ASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    asm
       MOV  EAX, Substr
       MOV  EDX, S
       MOV  ECX, &Offset
       test  eax, eax
       jz    @Nil
       test  edx, edx
       ...
    Une chose encore. Comme il y a un prologue, il y a aussi un épilogue inséré automatiquement par le compilateur après la dernière instruction du code, avant le END; final.

    Cet épilogue est indispensable pour restaurer l'état du registre EBP et assurer un retour correct à l'appelant. De plus en langage Pascal c'est la procédure appelée qui à la charge de supprimer de la pile tous les paramètres d'appel. C'est aussi l'épilogue qui remplit cette fonction.

    Exemple d'épilogue :
    Code ASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       Pop EBP  // restaure ebp
       RET 4  // retour et nettoyage de la pile
    L'argument de l'instruction RET est calculé par le compilateur pour correspondre à la taille totale de tous les paramètres à supprimer (içi un seul paramètre soit 4 octets).

    Conséquence importante : il est interdit de quitter la procédure autrement que par cet épilogue et donc d'utiliser une instruction RET à l'intérieur du programme.

    Il y a un RET dans le programme un peu après le label @Nil. Il faut remplacer ce RET par un JMP sur la dernière ligne du programme :
    Code ASM : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Nil:
       xor   eax, eax
    //   ret
       JMP @Fin
     
    ...
     
    @Fin:
    End;

    Voila, je pense qu'avec tout ça vous devriez vous en tirer.

    PS: Toutes ces indications sont données pour Delphi 7. Donc à vérifier pour une autre version, voire un autre compilateur.

  10. #10
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    Billets dans le blog
    1

    Par défaut

    effectivement j'avais fait une grosse erreur de gestion de la pile !
    J'ai fait les modifs : j'ai vérifié que le compilateur ajoutait bien l'épilogue !
    ça marche ! merci de votre aide ...
    Je sens que je vais avoir un peu plus souvent recours à l'assembleur...

  11. #11
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    Billets dans le blog
    1

    Par défaut

    Merci de ces explications qui ont du prendre de votre temps... Et que j'ai trouvées très claires.
    Mais si j'osais abuser...
    je viens de penser qu'il est possible de définir une fonction plus efficace et qui me serait très utile...
    En effet le serveur recherche des mots clés dans les requêtes afin de déterminer la réponse à apporter.
    or souvent ce mot clé apparait à une place bien déterminée dans la chaîne : il est inutile d'explorer la chaine si le premier caractère à cette position ne correspond pas au premier caractère de la sous chaine recherchée.
    Soit le mot clé est tout au début (GET, POST), soit sa place est définie comme dans "GET /url" si on s'intéresse à l'url, on sait qu'il faut regarder à partir de l'offset=5.
    j'ai essayé de voir si je pouvais modifier la fonction ci-dessus pour en faire une autre qui traiterait spécifiquement ces cas : il n'y aurait pas besoin de paramètre supplémentaire...
    or je butte sur certaines instructions que je comprends pas comme que veut dire cl ? ou encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
           movzx ebx, word ptr [esi+eax]
           cmp   bx, word ptr [esi+edx+1]
    je suppose que la modif doit être simple, car il suffit de débrancher dès que la comparaison échoue et ne pas poursuivre l'exploration de la chaine... Mais où cela se situe-t-il ?
    Si vous avez encore un peur de temps à me consacrer, merci !

  12. #12
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    Billets dans le blog
    1

    Par défaut Euréka !

    j'ai trouvé !
    Il n'est pas besoin d'aller dans l'algorithme de recherche... il suffit de modifier le paramètre qui va arrêter la recherche !
    en effet, la recherche ne peut se faire dans une longueur supérieure à offset+length(SubStr).
    il suffit de remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
           mov   esi, [edx-4]  //Length(Str)
           mov   ebx, [eax-4]  //Length(Substr)
           sub   esi, ecx      //effective length of Str
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
           mov   esi, [eax-4]  //Length(SubStr)
           mov   ebx, [eax-4]  //Length(Substr)
           add   esi, ecx      //effective length of search
    J'ai vérifié et cela marche.
    Est-ce que cette nouvelle fonction que je nommerai bien PosExact peut en intéresser d'autres et si oui, où dois-je la publier ?

  13. #13
    Membre averti

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

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

    Informations forums :
    Inscription : octobre 2009
    Messages : 102
    Points : 433
    Points
    433

    Par défaut

    Citation Envoyé par GerardJ
    j'ai trouvé !
    Félicitation ! donc en ce qui concerne la question de départ ?

    Quant-à votre dernière question,
    Citation Envoyé par GerardJ
    or je butte sur certaines instructions que je comprends pas comme
    que veut dire cl ? ou encore
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
         movzx ebx, word ptr [esi+eax]
         cmp   bx, word ptr [esi+edx+1]
    elle montre que vous avez encore quelques lacunes en matière de langage assemleur et ce serait sortir du sujet de ce forum que de les aborder içi. Je vous invite donc à vous reporter aux tutoriels "Assembleur" suivants : Noms des registres et Références mémoire
    Si après cela vous avez encore des questions, il serait mieux de les poser sur le forum assembleur où vous pourrez bénéficier des conseils de meilleurs spécialistes que moi.

    Enfin concernant votre dernière question
    Citation Envoyé par GerardJ
    Est-ce que cette nouvelle fonction que je nommerai bien PosExact peut en intéresser d'autres et si oui, où dois-je la publier ?
    je vous signale que les trois forums Pascal, Delphi et Assembleur disposent chacun d'un sous-forum "Contribuer" auquel je vous invite à vous référer.

  14. #14
    Membre du Club

    Inscrit en
    novembre 2008
    Messages
    28
    Détails du profil
    Informations forums :
    Inscription : novembre 2008
    Messages : 28
    Points : 52
    Points
    52
    Billets dans le blog
    1

    Par défaut

    Merci.
    J'ai ressorti le bouquin que j'avais acquis il y a quelque temps et je me suis plongé dedans et maintenant je comprends mieux l'architecture des registres et leur noM.
    mais cela ne va pas tout seul....

    en tout cas merci de vos conseils fort utiles...

Discussions similaires

  1. Utiliser propriété de mon objet dans une méthode callback ?
    Par StringBuilder dans le forum 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. 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