Inversion de chaîne [Résolu]

Signaler
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
-
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
-
Bonjour à tous,
A vrai dire je suis plutôt nouveau en asm et pas très bon lol. Mais bon, faut bien commencer un jour hein.
Pour me faire la main, j'ai écrit une petite méthode qui permet d'inverser une chaîne de caractère...

J'aimerais savoir si on peut faire mieux (sûrement que oui) et que les connaisseurs me corrigent
Merci d'avance

int

reverseStr(
char str1[],
char str2[])
{
  
int len = -1;

   __asm
   {
      XOR EAX, EAX
// Current char
      XOR EBX, EBX
// Counter
      XOR EBX, [len]

      XOR ECX, ECX

      XOR EDX, EDX      MOV ESI, [EBP+8]

// Reference (1st string)
      MOV EDI, [EBP+12]
// Reference (2nd string)   LoopStr:
      INC EBX
      MOV AL, [ESI+EBX]
      CMP AL, 0
      JNE LoopStr
     

// Save length
      MOV len, EBX 
      MOV [EDI+EBX],
'\0'
      MOV EDX, EBX
      DEC EDX
   LoopRev:DEC EBX
      MOV ECX, EDX
      MOV AL, [ESI+EBX]
      SUB ECX, EBX
      MOV [EDI+ECX], AL
      CMP EBX, 0
      JNE LoopRev
   }
  

return len;
}

<hr size="2" />-Blog-

4 réponses

Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
J'avais lu ta question comme d'hab un peu trop vite...
Tu voulais une inversion mais dans un autre buffer.
La routine retournera non pas la longueur qui risquerait fort de ne pas servir à grand chose mais plutot le terminateur null final, permettra un chainage direct si besoin et la longueur peut être sue illico aussi (fin - deb comme fait dans la routine):

__declspec(naked) char* __fastcall bnCpyRevStr(char *pdst, char *psrc){ // ECX pdst, EDX psrc
  __asm {
    mov     eax, ecx
    cmp     byte ptr[edx], 0
    je      short cpyrevEXIT
    mov     ecx, edx
    mov     [esp-4], ebx
goOUT:
    add     edx, 1
    cmp     byte ptr[edx], 0
    jne     short goOUT
    mov     ebx, edx
    sub     edx, ecx  ;// len = c - psrc
    sub     ebx, 1
fromSRC:
    mov     cl, [ebx]
    mov     [eax], cl
    sub     ebx, 1
    add     eax, 1
    sub     edx, 1
    jnz     short fromSRC
    mov     ebx, [esp-4]
cpyrevEXIT:
    mov     byte ptr[eax], 0
    ret     0
  }
}


void __stdcall TesteReverse()
{
  char buf[28];
  bnCpyRevStr(buf, "salut la foule");
  MessageBox(0, buf, "ok", 0);
}


#pragma comment(linker, "/entry:myWinMain")
__declspec(naked) void __stdcall myWinMain()
{
  __asm {
    call    TesteReverse
    push    0
    call    dword ptr ExitProcess
  }
}

ciao...
BruNews, MVP VC++
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
Calcul de longueur est totalement inutile, une chaine doit finir par un 0, suffit de mettre un pointeur sur le dernier char.

Cette routine se fait tranquille avec les 3 registres généraux et donc rien à PUSHer POPer.
Mettre de l'asm dans une fonction en C est la pire des solutions, ça empêche toute optimisation du compilo. Si on la fait en asm alors FULL asm ou rien.

__declspec(naked) void __fastcall bnRevStr(char *psz)
{ // ECX = psz
  __asm {
    cmp     byte ptr[ecx], 0
    mov     eax, ecx
    je      short revEXIT
goOUT:
    add     ecx, 1
    cmp     byte ptr[ecx], 0
    jne     short goOUT
goREV:
    sub     ecx, 1
    cmp     eax, ecx
    jae     short revEXIT
    mov     dl, [eax]
    mov     dh, [ecx]
    mov     [eax], dh
    mov     [ecx], dl
    add     eax, 1
    jmp     short goREV
revEXIT:
    ret     0
  }
}


void __stdcall TesteReverse()
{
  char buf[28];
  strcpy(buf, "salut la foule");
  MessageBox(0, buf, "ok", 0);
}


#pragma comment(linker, "/entry:myWinMain")
__declspec(naked) void __stdcall myWinMain()
{
  __asm {
    call    TesteReverse
    push    0
    call    dword ptr ExitProcess
  }
}

ciao...
BruNews, MVP VC++
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
30
OUPS, oublié d'appeler la routine:

void __stdcall TesteReverse()
{
  char buf[28];
  strcpy(buf, "salut la foule");
  bnRevStr(buf);
  MessageBox(0, buf, "ok", 0);
}

ciao...
BruNews, MVP VC++
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
54
Merci bien Brunews...
A vrai dire, cette synthaxe ne m'est pas encore tout à fait familière, va falloir que je regarde en détail 

<hr size="2" />-Blog-