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. :)
Je suggérerais un titre plus descriptif pour attirer plus d'attention. –
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
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