Delphi-Assembly-Funktion, die eine lange Zeichenfolge zurückgibt
Frage
Ich versuche, Inline-Assembly-Programmierung in Delphi zu lernen, und habe dieses Ziel gefunden Dieser Artikel sehr hilfreich.
Jetzt möchte ich eine Assembly-Funktion schreiben, die eine lange Zeichenfolge zurückgibt, insbesondere eine AnsiString
(der Einfachheit halber).ich habe geschrieben
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;
Erläuterung:
Eine Funktion, die eine Zeichenfolge zurückgibt, ist unsichtbar var result: AnsiString
(in diesem Fall) Parameter, also am Anfang der Funktion eax
sollte die Adresse der resultierenden Zeichenfolge enthalten.Ich habe dann eingestellt edx
Und ecx
bis 3 bzw. 1252 und rufen Sie dann an System._LStrSetLength
.Tatsächlich tue ich das
_LStrSetLength(@result, 3, 1252)
Dabei ist 3 die neue Länge der Zeichenfolge (in Zeichen = Bytes) und 1252 der Standard Windows-1252 Codepage.
Dann weiß ich das eax
Ist die Adresse des ersten Zeichens der Zeichenfolge, ich habe die Zeichenfolge einfach auf „ABC“ gesetzt.Aber es funktioniert nicht – es gibt mir unsinnige Daten oder EAccessViolation.Was ist das Problem?
Aktualisieren
Jetzt haben wir zwei scheinbar funktionierende Implementierungen von myfunc
, einer beschäftigt NewAnsiString
und einer beschäftigt LStrSetLength
.Ich frage mich, ob beide korrekt sind, in dem Sinne, dass sie Delphis interne Verarbeitung von Zeichenfolgen (Referenzzählung, automatisches Freigeben usw.) nicht durcheinander bringen.
Lösung
Sie müssen Folgendes verwenden:
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;
Es wird eine Zeichenfolge „210“ zurückgegeben ...
Und es ist immer eine gute Idee, einen {$ifdef UNICODE}-Block einzufügen, damit Ihr Code mit Delphi-Versionen vor 2009 kompatibel ist.
Andere Tipps
Mit der hervorragenden Hilfe von A. Bouchez gelang es mir, meinen eigenen Code zu korrigieren 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;