我正在尝试在Delphi中学习内联汇编编程,为此我发现this article非常有帮助。
现在我希望编写一个返回长字符串的汇编函数,特别是AnsiString
(为简单起见)。我写了
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;
说明:
返回字符串的函数有一个不可见的var result: AnsiString
(在本例中)参数,因此,在函数的开头,eax
应该保存结果字符串的地址。然后,我将edx
和ecx
分别设置为3和1252,然后调用System._LStrSetLength
。实际上,我做了
_LStrSetLength(@result, 3, 1252)
其中3是字符串的新长度(字符=字节),1252是标准windows-1252代码页。
然后,知道eax
是the address of the first character of the string,我只需将字符串设置为“ABC”。但它不起作用 - 它给了我无意义的数据或EAccessViolation。有什么问题?
现在我们有myfunc
两个看似有效的实施方案,一个使用NewAnsiString
,一个使用LStrSetLength
。我不禁想知道它们是否都是正确的,因为它们不会弄乱德尔福对字符串的内部处理(引用计数,自动释放等)。
答案 0 :(得分:3)
你必须使用某种:
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;
它会返回'210'字符串......
在2009年之前使用{$ ifdef UNICODE}块来使代码与Delphi版本兼容总是一个好主意。
答案 1 :(得分:1)
在A.Bouchez的出色帮助下,我设法纠正了我自己的代码,使用了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;