2010-07-22 5 views
2

J'essaie d'apprendre la programmation d'assemblage en ligne dans Delphi, et à cette fin, j'ai trouvé this article très utile.Fonction d'assemblage Delphi Renvoyer une longue chaîne

Maintenant, je souhaite écrire une fonction d'assemblage retournant une longue chaîne, en particulier AnsiString (pour plus de simplicité). Je l'ai écrit

function myfunc: AnsiString; 
asm 
    // eax = @result 
    mov edx, 3 
    mov ecx, 1252 
    call [email protected] 
    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 paramètre var result: AnsiString invisible (dans ce cas), donc, au début de la fonction, eax devrait tenir l'adresse de la chaîne résultante . J'ai ensuite défini edx et ecx à 3 et 1252, respectivement, puis appelez System._LStrSetLength. En effet, je

_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 codepage. Puis, sachant que eax est the address of the first character of the string, je simplement définir la chaîne à "ABC". Mais cela ne fonctionne pas - il me donne des données absurdes ou EAccessViolation. Quel est le problème?

Mise à jour

Maintenant, nous avons deux implémentations de travail apparemment de myfunc, un employant NewAnsiString et un emploi LStrSetLength. Je ne peux pas m'empêcher de me demander si les deux sont corrects, dans le sens où ils ne gâchent pas le traitement interne des chaînes de Delphi (comptage des références, libération automatique, etc.).

+0

Pour les questions Delphi/Asm, le forum BASM d'Embarcadero est également utile. Travailler avec des chaînes, vous pourriez également être intéressé par ce fil: http://forums.embarcadero.com/thread.jspa?threadID=20231 – PhiS

Répondre

3

Vous devez utiliser une sorte de:

function myfunc: AnsiString; 
asm 
    push eax // save @result 
    call [email protected] 
    mov eax,3     {Length} 
{$ifdef UNICODE} 
    mov edx,1252 // code page for Delphi 2009/2010 
{$endif} 
    call [email protected] 
    pop edx 
    mov [edx],eax 
    mov [eax],$303132 
end; 

Il retournera un '210' string ...

Et il est toujours une bonne idée de mettre un {$ ifdef UNICODE} bloc pour ont votre code compatible avec la version de Delphi avant 2009.

+0

Cela fonctionne. Si je comprends bien le code, '@ result' est fixé et est un pointeur sur la chaîne, qui est un pointeur seul, de sorte que le premier caractère de la chaîne est conceptuellement' (@result) ^^ ', et non à '(@result) ^'? –

+0

En effet. Vous avez le point ici. –

+0

A propos de la fonction à appeler, l'appel de NewAnsiString seulement entraînera des fuites de mémoire ici. L'appel de LStrSetLength est donc la meilleure option: elle appelle NewAnsiString si la chaîne de résultats est '', ou ReallocMem si la chaîne de résultats contient déjà des caractères. Le plus rapide est d'utiliser LStrClr puis NewAnsiString, car ReallocMem va déplacer les données précédentes stockées dans le résultat. Voir le code de la fonction StringOfChar() dans System.pas J'ai mis à jour mon exemple. –

1

avec l'excellente aide A.Bouchez, je réussi à corriger mon propre code, en utilisant LStrSetLength:

function myfunc: AnsiString; 
asm 

    push eax 

    // eax = @result 
    mov edx, 3 
    mov ecx, 1252 
    call [email protected] 

    pop eax 

    mov ecx, [eax] 

    mov [ecx], 'A' 
    mov [ecx] + 1, 'B' 
    mov [ecx] + 2, 'C' 

end; 
Questions connexes