Функция сборки Delphi, возвращающая длинную строку - PullRequest
2 голосов
/ 23 июля 2010

Я пытаюсь изучать программирование встроенной сборки в 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 соответственно, а затем вызываю System._LStrSetLength. По сути, я делаю

  _LStrSetLength(@result, 3, 1252)

, где 3 - новая длина строки (в символах = байты), а 1252 - стандартная windows-1252 кодовая страница.

Затем, зная, что eax является адресом первого символа строки , я просто установил строку в "ABC". Но это не работает - это дает мне бессмысленные данные или EAccessViolation. В чем проблема?

Обновление

Теперь у нас есть две вроде бы работающие реализации myfunc, одна из которых использует NewAnsiString, а другая - LStrSetLength. Я не могу не задаться вопросом, верны ли они оба, в том смысле, что они не портят внутреннюю обработку строк в Delphi (подсчет ссылок, автоматическое освобождение и т.

Ответы [ 2 ]

3 голосов
/ 23 июля 2010

Вы должны использовать что-то вроде:

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}, чтобы ваш код был совместим с версией Delphi до 2009 года.

1 голос
/ 23 июля 2010

С превосходной помощью А.Бучеза мне удалось исправить свой собственный код, используя 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;
...