Fonction d'assemblage Delphi renvoyant une longue chaîne
Question
J'essaie d'apprendre la programmation en assembleur en ligne dans Delphi, et à cette fin j'ai trouvé Cet article très utile.
Maintenant, je souhaite écrire une fonction d'assemblage renvoyant une longue chaîne, en particulier un AnsiString
(pour la simplicité).j'ai écrit
function myfunc: AnsiString;
asm
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
mov [eax + 0], ord('A')
mov [eax + 1], ord('B')
mov [eax + 2], ord('C')
end;
Explication:
Une fonction renvoyant une chaîne a un invisible var result: AnsiString
(dans ce cas) paramètre, donc, au début de la fonction, eax
doit contenir l’adresse de la chaîne résultante.J'ai ensuite mis edx
et ecx
au 3 et au 1252, respectivement, puis appelez System._LStrSetLength
.En effet, je le fais
_LStrSetLength(@result, 3, 1252)
où 3 est la nouvelle longueur de la chaîne (en caractères = octets) et 1252 est la norme Windows-1252 page de code.
Alors, sachant que eax
est l'adresse du premier caractère de la chaîne, j'ai simplement défini la chaîne sur "ABC".Mais ça ne marche pas – ça me donne des données absurdes ou EAccessViolation.Quel est le problème?
Mise à jour
Nous avons maintenant deux implémentations apparemment fonctionnelles de myfunc
, l'un employant NewAnsiString
et un employant LStrSetLength
.Je ne peux m'empêcher de me demander si les deux sont corrects, dans le sens où ils ne gâchent pas la gestion interne des chaînes par Delphi (comptage de références, libération automatique, etc.).
La solution
Vous devez utiliser une sorte de :
function myfunc: AnsiString;
asm
push eax // save @result
call system.@LStrClr
mov eax,3 {Length}
{$ifdef UNICODE}
mov edx,1252 // code page for Delphi 2009/2010
{$endif}
call system.@NewAnsiString
pop edx
mov [edx],eax
mov [eax],$303132
end;
Il renverra une chaîne '210'...
Et c'est toujours une bonne idée de mettre un bloc {$ifdef UNICODE} pour que votre code soit compatible avec la version de Delphi antérieure à 2009.
Autres conseils
Avec l'excellente aide de A.Bouchez, j'ai réussi à corriger mon propre code, en employant LStrSetLength
:
function myfunc: AnsiString;
asm
push eax
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
pop eax
mov ecx, [eax]
mov [ecx], 'A'
mov [ecx] + 1, 'B'
mov [ecx] + 2, 'C'
end;