2017-02-24 2 views
0

Voici donc le problème: j'essaie actuellement de recoder certaines des fonctions de clib en langage assembleur (c'est un projet d'école pour commencer avec l'assemblage). La fonction sur laquelle je travaille actuellement est strcat. Pour l'instant, mon objectif est de rester simple et de suivre les quelques règles suivantes:Implémenter StrCat dans l'assemblage x86_64

  • Si la chaîne de destination est NULL, le retour (en rax) la chaîne source.
  • Si la chaîne source est NULL, renvoyez (dans rax) la chaîne de destination.
  • Copiez la chaîne source à la fin de la chaîne de destination (y compris la fin de 0) et renvoyez (toujours dans rax) le résultat.

Voici mon code:

ft_strcat: 
    push rbp 
    mov  rbp, rsp ; saving the stack state 

    push rdi ; seems to work better this way but I don't know why 
    mov  rdi, [rsp + 24] ; destination string 
    mov  rsi, [rsp + 16] ; source string 

    push rdi ; keeping the adress to return 
    test rsi, rsi ; in case one of the strings is NULL 
    je  getdest 
    test rdi, rdi 
    je  getsrc 

    toend: ; to go to the end of the destination string 
     cmp  byte [rdi], 0x0 ; is it the end? 
     je  cpy ; if so, go to the next part 
     inc  rdi ; else keep going 
     jmp  toend ; loop 

    cpy: ; to copy the source string to the end of the destination string 
     mov  al, byte[rsi] ; getting the byte to copy 
     mov  byte [rdi], al ; copying it 
     cmp  byte [rsi], 0x0 ; it is the end of the source string? 
     je  getdest ; if so, jump to the end 
     inc  rdi ; else increase counter 
     inc  rsi 
     jmp  cpy ; loop 

    getdest: ; if source is NULL or copy is done 
     pop  rax 
     jmp  end 
    getsrc: ; if destination is NULL 
     mov  rax, rsi 
    end: 

    pop  rdi ; get rdi back 
    leave 
    ret ; finally return... 

J'ai essayé un très grand nombre de façons différentes (movsb, l'argument qui passe avec les registres [directement], en changeant les registres ...) toujours d'atteindre le même résultat :

  • Segfault
  • caractères étranges dans la chaîne (si on peut encore l'appeler une chaîne ...)

Cette version conserve la partie destination intacte mais ajoute les caractères non-caractères à la fin: ���Ph� (c'est juste un exemple mais les caractères ont tendance à changer de temps en temps) ...
Je pensais que peut-être vous pourrait m'aider (au moins me donner une idée de l'endroit où changer les choses, ou ce qui peut être mauvais dans mon code), parce que j'ai regardé partout sur Internet et n'ai jamais trouvé des choses qui m'aideraient vraiment. Oh, en passant, je travaille avec Nasm sur Ubuntu (oui, je sais;)).

Merci à tous ceux qui répondront. :)

+0

Je suggérerais un titre plus descriptif pour attirer plus d'attention. –

+0

Je suggère contre une telle API, ne pas retourner la source lorsque la destination est invalide. Si la source est une chaîne constante en lecture seule, et que vous enchaînerez plusieurs appels 'strcat', le premier ayant échoué pour une raison quelconque à recevoir le tampon' null' ("new" a échoué?), Alors le 'strcat' suivant de la chaîne segfault, si vous réutilisez le pointeur 'buffer' de' rax' (il s'agit d'un commentaire sans rapport avec votre implémentation). – Ped7g

+0

Le corps de la routine semble correct, mais je pense que seul le cas 'rdi == null' libère correctement la pile. 'getdest:' fera apparaître le rdi dans rax en premier, puis il affichera la valeur suivante (rbp?) dans rdi deuxième fois. Et puis tout va vers le sud (oh attends, ça ne part pas, 'leave' va te sauver, seul' rdi' n'est pas buffer) ...BTW qui devrait être facile à voir dans le débogueur, il suffit de noter votre 'rsp' après avoir fait' push rbp' et mettre breakpoint à 'leave', le' rsp' devrait correspondre .. Maintenant, je me souviens de ce que 'leave' fait, et en fait pas , 'rsp' peut être éteint, mais vous ne le vouliez toujours pas comme ça? – Ped7g

Répondre

0

très probablement son

mov  rdi, [rsp + 32] ; destination string 
mov  rsi, [rsp + 24] ; source string 

ou

mov  rdi, [rbp + 24] ; destination string 
mov  rsi, [rbp + 16] ; source string 

selon ce que vous aimez mieux

Dans votre version actuelle, RSI contient le retour adr de la fonction. Si actuellement vous ajoutez des éléments à la destination, essayez

mov  rdi, [rsp + 24] 
mov  rsi, [rsp + 32]