Delphi 汇编块中的异常行为

发布于 2024-10-16 10:10:35 字数 1167 浏览 2 评论 0原文

我在使用 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] into 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] 可以解决该问题。对此感到抱歉。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风吹过旳痕迹 2024-10-23 10:10:35

在第一种情况下,mov eax,[asdf],汇编器将查找asdf并发现它是实例中偏移量4的字段。因为您使用了没有基址的间接寻址模式,所以它只会对偏移量进行编码(对于汇编器来说,它看起来像 0 + asdf)。如果你这样写:mov eax, [eax].asdf,它会被编码为 mov eax, [eax+4]。 (这里 eax 包含从调用者传入的 Self)。

在第二种情况下,汇编器将查找 Temp 并发现它是一个由 EBP 索引的局部变量。因为它知道要使用的基地址寄存器,所以它可以决定将其编码为[EBP-4]。

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].

帅气称霸 2024-10-23 10:10:35

方法接收 EAX 寄存器中的 Self 指针。您必须使用该值作为访问该对象的基值。因此,您的代码将类似于:

mov ebx, TBlah[eax].asdf

请参阅 http://www.delphi3000.com/articles/article_3770。以 .asp 为例。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文