Delphi汇编块中的异常行为

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.

这只是举个例子(将[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
在第一个例子中,mov eax, [asdf],汇编器将查找asdf并发现它是实例中偏移为4的字段。因为您使用了没有基地址的间接寻址模式,所以它只编码了偏移量(在汇编器中看起来像0+asdf)。如果您写成这样:mov eax,[eax].asdf,它会被编码为mov eax,[eax + 4]。(这里eax包含从调用者传入的Self)。
在第二个例子中,汇编器将查找Temp并看到它是通过EBP索引的局部变量。因为它知道要使用的基地址寄存器,所以它可以决定将其编码为[EBP-4]。

10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接