Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 返回长字符串的Delphi汇编函数_String_Delphi_Function_Assembly_Basm - Fatal编程技术网

String 返回长字符串的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

我正在努力学习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 [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论坛也很有用。使用字符串时,您可能还对以下线程感兴趣: