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.).

Était-ce utile?

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top