德尔福装配块中的异常行为

Oke*_*key 6 delphi assembly instance-variables basm

我正在使用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.
Run Code Online (Sandbox Code Playgroud)

这只是举例的缘故(mov荷兰国际集团[asdf]eax没有做太多,但它工作的例子).如果你看看这个程序的程序集,你会看到

mov eax, [asdf]
Run Code Online (Sandbox Code Playgroud)

已经变成了

mov eax, ds:[4]
Run Code Online (Sandbox Code Playgroud)

(由OllyDbg代表)显然崩溃了.但是,如果你这样做:

var
    temp: TAsdf;
begin
    temp := asdf;

    asm
        int 3;
        mov eax, [temp];
    end;
Run Code Online (Sandbox Code Playgroud)

它改为mov eax,[ebp-4]有效.为什么是这样?我通常使用C++而且我习惯使用像这样的实例变量,可能是因为我使用的是实例变量错误.

编辑:是的,就是这样.更改mov eax, [asdf]mov eax, [Self.asdf]解决问题.对于那个很抱歉.

All*_*uer 12

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

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


Jim*_*hel 10

方法接收SelfEAX寄存器中的指针.您必须使用该值作为访问对象的基值.所以你的代码将是这样的:

mov ebx, TBlah[eax].asdf
Run Code Online (Sandbox Code Playgroud)

有关示例,请参见http://www.delphi3000.com/articles/article_3770.asp.