2

私は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、結果の文字列のアドレスを保持する必要があります。次に、とをそれぞれ3と1252に設定edxしてから、を呼び出します。事実上、私はしますecxSystem._LStrSetLength

  _LStrSetLength(@result, 3, 1252)

ここで、3は文字列の新しい長さ(文字数=バイト)であり、1252は標準のwindows-1252コードページです。

次に、それが文字列の最初の文字のアドレスであるeaxことを知って、文字列を「ABC」に設定するだけです。しかし、それは機能しません-それは私にナンセンスなデータまたはEAccessViolationを与えます。何が問題ですか?

アップデート

これで、2つの一見機能している実装がありますmyfunc。1つはを採用しNewAnsiString、もう1つはを採用してLStrSetLengthいます。Delphiの文字列の内部処理(参照カウント、自動解放など)を台無しにしないという意味で、両方が正しいかどうか疑問に思わざるを得ません。

4

2 に答える 2

3

次のようなものを使用する必要があります。

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 と互換性のあるコードを作成することを常にお勧めします。

于 2010-07-22T21:23:40.677 に答える
1

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;
于 2010-07-22T21:40:14.563 に答える