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

  _LStrSetLength(@result, 3, 1252)

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

然后,知道了 eax字符串第一个字符的地址, ,我只是将字符串设置为“ABC”。但它不起作用 - 它给了我无意义的数据或 EAccessViolation。问题是什么?

更新

现在我们有两个看似有效的实现 myfunc, 一名雇用 NewAnsiString 和一名雇用 LStrSetLength. 。我忍不住想知道它们是否都是正确的,因为它们不会扰乱 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”字符串...

放置一个 {$ifdef UNICODE} 块以使您的代码与 2009 年之前的 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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top