Inversion de chaîne

Résolu
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 - 18 déc. 2006 à 18:02
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 - 19 déc. 2006 à 21:29
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

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 déc. 2006 à 21:24
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++
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 déc. 2006 à 20:37
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++
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 déc. 2006 à 20:39
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++
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
19 déc. 2006 à 21:29
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-
0
Rejoignez-nous