问题
I am trying to learn inline assembly programming in Delphi, and to this end I have found this article highly helpful.
Now I wish to write an assembly function returning a long string, specifically an AnsiString
(for simplicity). I have written
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;
Explanation:
A function returning a string has an invisible var result: AnsiString
(in this case) parameter, so, at the beginning of the function, eax
should hold the address of the resulting string. I then set edx
and ecx
to 3 and 1252, respectively, and then call System._LStrSetLength
. In effect, I do
_LStrSetLength(@result, 3, 1252)
where 3 is the new length of the string (in characters = bytes) and 1252 is the standard windows-1252 codepage.
Then, knowing that eax
is the address of the first character of the string, I simply set the string to "ABC". But it does not work - it gives me nonsense data or EAccessViolation. What is the problem?
Update
Now we have two seemingly working implementations of myfunc
, one employing NewAnsiString
and one employing LStrSetLength
. I cannot help but wonder if both of them are correct, in the sense that they do not mess upp Delphi's internal handling of strings (reference counting, automatic freeing, etc.).
回答1:
You have to use some kind of:
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;
It will return a '210' string...
And it's always a good idea of putting a {$ifdef UNICODE} block to have your code compatible with version of Delphi prior to 2009.
回答2:
With the excellent aid of A.Bouchez, I managed to correct my own code, employing 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;
来源:https://stackoverflow.com/questions/3313447/delphi-assembly-function-returning-a-long-string