【问题标题】:Delphi Assembly Function Returning a Long StringDelphi 汇编函数返回一个长字符串
【发布时间】:2010-07-22 21:02:26
【问题描述】:

我正在尝试在 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 应该保存结果字符串的地址。然后我将edxecx 分别设置为3 和1252,然后调用System._LStrSetLength。实际上,我愿意

  _LStrSetLength(@result, 3, 1252)

其中 3 是字符串的新长度(字符 = 字节),1252 是标准 windows-1252 代码页。

然后,知道eaxthe address of the first character of the string,我只需将字符串设置为“ABC”。但它不起作用 - 它给了我无意义的数据或 EAccessViolation。有什么问题?

更新

现在我们有两个看似有效的myfunc 实现,一个使用NewAnsiString,一个使用LStrSetLength。我不禁想知道它们是否都正确,因为它们不会破坏 Delphi 对字符串的内部处理(引用计数、自动释放等)。

【问题讨论】:

标签: string delphi function assembly basm


【解决方案1】:

你必须使用某种:

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' 字符串...

放置一个 {$ifdef UNICODE} 块以使您的代码与 2009 年之前的 Delphi 版本兼容总是一个好主意。

【讨论】:

  • 这行得通。如果我正确理解代码,@result 是固定的,是一个指向字符串的指针,它本身就是一个指针,因此字符串的第一个字符在概念上是(@result)^^,而不是(@result)^?跨度>
  • 关于要调用的函数,这里只调用NewAnsiString会导致一些内存泄漏。因此调用 LStrSetLength 是最好的选择:如果结果字符串是 '',它将调用 NewAnsiString,如果结果字符串已经包含字符,它将调用 ReallocMem。最快的是使用 LStrClr 然后 NewAnsiString,因为 ReallocMem 会移动之前存储在 result 中的数据。请参阅 System.pas 中的 StringOfChar() 函数代码我已经更新了我的示例。
【解决方案2】:

在 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;

【讨论】:

    猜你喜欢
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多