unusual behaviour in delphi assembly block
Asked Answered
T

2

6

I am running into some weird behaviour with Delphi's inline assembly, as demonstrated in this very short and simple program:

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.

It's just for the sake of example (moving [asdf] into eax doesn't do much, but it works for the example). If you look at the assembly for this program, you'll see that

mov eax, [asdf]

has been turned into

mov eax, ds:[4]

(as represented by OllyDbg) which obviously crashes. However, if you do this:

var
    temp: TAsdf;
begin
    temp := asdf;

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

It changes to mov eax, [ebp-4] which works. Why is this? I'm usually working with C++ and I'm used to using instance vars like that, it may be that I'm using instance variables wrong.

EDIT: Yep, that was it. Changing mov eax, [asdf] to mov eax, [Self.asdf] fixes the problem. Sorry about that.

Tenpenny answered 9/2, 2011 at 22:1 Comment(0)
B
10

A method receives the Self pointer in the EAX register. You have to use that value as the base value for accessing the object. So your code would be something like:

mov ebx, TBlah[eax].asdf

See http://www.delphi3000.com/articles/article_3770.asp for an example.

Bacteroid answered 9/2, 2011 at 22:11 Comment(0)
R
12

In the first case, mov eax,[asdf], the assembler will look up asdf and discover it is a field of offset 4 in the instance. Because you used an indirect addressing mode without a base address, it will only encode the offset (it looks like 0 + asdf to the assembler). Had you written it like this: mov eax, [eax].asdf, it would have been encoded as mov eax, [eax+4]. (here eax contains Self as passed in from the caller).

In the second case, the assembler will look up Temp and see that it is a local variable indexed by EBP. Because it knows the base address register to use, it can decide to encode it as [EBP-4].

Repetend answered 9/2, 2011 at 22:11 Comment(0)
B
10

A method receives the Self pointer in the EAX register. You have to use that value as the base value for accessing the object. So your code would be something like:

mov ebx, TBlah[eax].asdf

See http://www.delphi3000.com/articles/article_3770.asp for an example.

Bacteroid answered 9/2, 2011 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.