Функция ассемблера Delphi, возвращающая длинную строку

StackOverflow https://stackoverflow.com/questions/3313447

Вопрос

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

Другие советы

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