Pregunta

Estoy intentando aprender programación ensambladora en línea en Delphi y, para ello, he encontrado Este artículo muy útil.

Ahora deseo escribir una función ensambladora que devuelva una cadena larga, específicamente una AnsiString (por simplicidad).he 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;

Explicación:

Una función que devuelve una cadena tiene un carácter invisible. var result: AnsiString (en este caso) parámetro, por lo que, al comienzo de la función, eax debe contener la dirección de la cadena resultante.entonces puse edx y ecx al 3 y 1252, respectivamente, y luego llamar System._LStrSetLength.En efecto, lo hago

  _LStrSetLength(@result, 3, 1252)

donde 3 es la nueva longitud de la cadena (en caracteres = bytes) y 1252 es el estándar ventanas-1252 página de código.

Entonces, sabiendo que eax es la dirección del primer carácter de la cadena, simplemente configuro la cadena en "ABC".Pero no funciona: me proporciona datos sin sentido o EAccessViolation.¿Cuál es el problema?

Actualizar

Ahora tenemos dos implementaciones aparentemente funcionales de myfunc, uno que emplea NewAnsiString y uno que emplea LStrSetLength.No puedo evitar preguntarme si ambos son correctos, en el sentido de que no estropean el manejo interno de cadenas por parte de Delphi (recuento de referencias, liberación automática, etc.).

¿Fue útil?

Solución

Tienes que usar algún 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;

Devolverá una cadena '210'...

Y siempre es una buena idea poner un bloque {$ifdef UNICODE} para que su código sea compatible con la versión de Delphi anterior a 2009.

Otros consejos

Con la excelente ayuda de A.Bouchez, logré corregir mi propio código, empleando 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top