необычное поведение в сборочном блоке delphi - PullRequest
6 голосов
/ 10 февраля 2011

Я сталкиваюсь со странным поведением встроенной сборки 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.

Это просто ради примера (mov вставка [asdf] в eax мало что делает, но работает для примера). Если вы посмотрите на сборку для этой программы, вы увидите, что

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] устраняет проблему. Извините за это.

Ответы [ 2 ]

12 голосов
/ 10 февраля 2011

В первом случае mov eax, [asdf], ассемблер будет искать в формате asdf и обнаружит, что это поле смещения 4 в данном примере.Поскольку вы использовали режим косвенной адресации без базового адреса, он будет кодировать только смещение (для ассемблера это выглядит как 0 + asdf).Если бы вы написали это так: mov eax, [eax] .asdf, это было бы закодировано как mov eax, [eax + 4].(здесь eax содержит Self, как передано от вызывающей стороны).

Во втором случае ассемблер ищет Temp и видит, что это локальная переменная, проиндексированная EBP.Поскольку ему известен регистр базовых адресов, который он может использовать, он может решить закодировать его как [EBP-4].

10 голосов
/ 10 февраля 2011

Метод получает указатель Self в регистре EAX. Вы должны использовать это значение в качестве базового значения для доступа к объекту. Таким образом, ваш код будет выглядеть примерно так:

mov ebx, TBlah[eax].asdf

См. http://www.delphi3000.com/articles/article_3770.asp для примера.

...