Pergunta

Estou tentando aprender programação assembly inline em Delphi e, para isso, descobri Este artigo altamente útil.

Agora desejo escrever uma função assembly retornando uma string longa, especificamente um AnsiString (Pela simplicidade).Eu tenho escrito

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;

Explicação:

Uma função que retorna uma string tem um invisível var result: AnsiString (neste caso) parâmetro, então, no início da função, eax deve conter o endereço da string resultante.Eu então configurei edx e ecx para 3 e 1252, respectivamente, e depois ligue System._LStrSetLength.Com efeito, eu faço

  _LStrSetLength(@result, 3, 1252)

onde 3 é o novo comprimento da string (em caracteres = bytes) e 1252 é o padrão janelas-1252 página de código.

Então, sabendo disso eax é o endereço do primeiro caractere da string, simplesmente defino a string como "ABC".Mas não funciona - me fornece dados sem sentido ou EAccessViolation.Qual é o problema?

Atualizar

Agora temos duas implementações aparentemente funcionais de myfunc, um empregando NewAnsiString e um que emprega LStrSetLength.Não posso deixar de me perguntar se ambos estão corretos, no sentido de que não atrapalham o manuseio interno de strings do Delphi (contagem de referências, liberação automática, etc.).

Foi útil?

Solução

Você tem que usar algum tipo de:

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;

Ele retornará uma string '210' ...

E é sempre uma boa ideia colocar um bloco {$ifdef UNICODE} para ter seu código compatível com a versão do Delphi anterior a 2009.

Outras dicas

Com a excelente ajuda de A.Bouchez consegui corrigir meu próprio código, empregando 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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top