String 返回长字符串的Delphi汇编函数
我正在努力学习Delphi中的内联汇编编程,为此我发现非常有用 现在我想编写一个汇编函数,返回一个长字符串,特别是一个String 返回长字符串的Delphi汇编函数,string,delphi,function,assembly,basm,String,Delphi,Function,Assembly,Basm,我正在努力学习Delphi中的内联汇编编程,为此我发现非常有用 现在我想编写一个汇编函数,返回一个长字符串,特别是一个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
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,然后调用系统。事实上,我知道
_LStrSetLength(@result, 3, 1252)
其中3是字符串的新长度(字符=字节),1252是标准代码页
然后,知道eax
是,我只需将字符串设置为“ABC”。但它不起作用——它给我提供了无意义的数据或是违反规定。有什么问题
更新
现在我们有了两个看似有效的myfunc
实现,一个采用NewAnsiString
,另一个采用LStrSetLength
。我不禁怀疑它们是否都是正确的,因为它们不会扰乱upp Delphi对字符串的内部处理(引用计数、自动释放等)。您必须使用某种类型的:
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版本兼容。您必须使用某种类型的:
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版本兼容始终是一个好主意。在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;
在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;
这很有效。如果我正确理解了代码,@result
是固定的,是指向字符串的指针,字符串本身就是指针,因此字符串的第一个字符在概念上是(@result)^
,而不是在(@result)^
?关于要调用的函数,只调用NewAnsiString会导致一些内存泄漏。因此,调用LStrSetLength是最好的选择:如果结果字符串为“”,它将调用NewAnsiString;如果结果字符串已经包含字符,它将调用ReallocMem。最快的方法是使用lstrcr,然后使用NewAnsiString,因为ReallocMem将移动存储在result中的先前数据。请参阅System.pas中的StringOfChar()函数代码,我已经更新了我的示例。如果我正确理解了代码,@result
是固定的,是指向字符串的指针,字符串本身就是指针,因此字符串的第一个字符在概念上是(@result)^
,而不是在(@result)^
?关于要调用的函数,只调用NewAnsiString会导致一些内存泄漏。因此,调用LStrSetLength是最好的选择:如果结果字符串为“”,它将调用NewAnsiString;如果结果字符串已经包含字符,它将调用ReallocMem。最快的方法是使用lstrcr,然后使用NewAnsiString,因为ReallocMem将移动存储在result中的先前数据。参见System.pas中的StringOfChar()函数代码,我已经更新了我的示例。对于Delphi/Asm问题,Embarcadero的BASM论坛也很有用。使用字符串时,您可能还对该线程感兴趣:对于Delphi/Asm问题,Embarcadero的BASM论坛也很有用。使用字符串时,您可能还对以下线程感兴趣: