6

この非常に短くて単純なプログラムで示されているように、Delphi のインライン アセンブリで奇妙な動作が発生しています。

program test;

{$APPTYPE CONSOLE}

uses
    SysUtils;

type
    TAsdf = class
    public
        int: Integer;
    end;

    TBlah = class
    public
        asdf: TAsdf;

        constructor Create(a: TAsdf);

        procedure Test;
    end;

constructor TBlah.Create(a: TAsdf);
begin
    asdf := a;
end;

procedure TBlah.Test;
begin
    asm
        mov eax, [asdf]
    end;
end;

var
    asdf: TAsdf;
    blah: TBlah;

begin
    asdf := TAsdf.Create;

    blah := TBlah.Create(asdf);

    blah.Test;

    readln;
end.

これは単なる例です ( moving [asdf]intoeaxはあまり機能しませんが、この例では機能します)。このプログラムのアセンブリを見ると、

mov eax, [asdf]

に変わりました

mov eax, ds:[4]

(OllyDbg で表される) これは明らかにクラッシュします。ただし、これを行う場合:

var
    temp: TAsdf;
begin
    temp := asdf;

    asm
        int 3;
        mov eax, [temp];
    end;

動作するmov eax、[ebp-4]に変わります。どうしてこれなの?私は通常C++で作業しており、そのようなインスタンス変数を使用することに慣れています。インスタンス変数を間違って使用している可能性があります。

編集:はい、それでした。に変更mov eax, [asdf]するmov eax, [Self.asdf]と問題が解決します。申し訳ありません。

4

2 に答える 2

12

最初のケース mov eax,[asdf] では、アセンブラは asdf を検索し、それがインスタンス内のオフセット 4 のフィールドであることを検出します。ベース アドレスなしで間接アドレッシング モードを使用したため、オフセットのみがエンコードされます (アセンブラーには 0 + asdf のように見えます)。mov eax, [eax].asdf のように記述した場合、mov eax, [eax+4] としてエンコードされます。(ここで eax には、呼び出し元から渡された Self が含まれています)。

2 番目のケースでは、アセンブラは Temp を検索し、それが EBP によってインデックス付けされたローカル変数であることを確認します。使用するベース アドレス レジスタがわかっているため、[EBP-4] としてエンコードすることを決定できます。

于 2011-02-09T22:11:58.740 に答える
10

メソッドはSelf、EAX レジスターでポインターを受け取ります。オブジェクトにアクセスするためのベース値としてその値を使用する必要があります。したがって、コードは次のようになります。

mov ebx, TBlah[eax].asdf

例については、 http://www.delphi3000.com/articles/article_3770.aspを参照してください。

于 2011-02-09T22:11:34.947 に答える