-1

我对 Pascal 很了解,但无法理解这个汇编函数出了什么问题:

{$ASMMODE intel}
function SomeType.doSomething : boolean; assembler;
var i : integer; // for testing
asm
   mov EAX, field
   mov i, EAX // line 42
   and EAX, 4
   mov i, EAX
    //...
end;

类声明:

type
    SomeType = class(TObject)
    private
        field : integer;
        function doSomething : boolean;
    // ...
    end;

field(类的一个字段SomeType)在调用此方法之前为 4 时,IDE(Lazarus)将向我报告i在第 42 行分配了 8(请参见上面的行编号)。

我缺少关于内联程序集的内容吗?

为什么字段的值没有EAX正确存储和/或加载?

更新:我想我可能瞄准 64 位。

4

1 回答 1

6

读取对象的字段并不像普通的从内存中读取那样简单。回想一下,成员访问是隐式通过Self的,所以当您编写field代码时,您真正的意思是Self.field. 要从中读取值Self.field,编译器实际上需要将您的代码替换为以下内容:

mov EAX, dword ptr [EAX + offset SomeType.field]

您可以检查调试器中的 CPU 视图,看看这是否真的发生了。

我想你会发现它不是。如果 Free Pascal 以与 Delphi 相同的方式解释此代码,则对的裸引用field不包括隐式Self部分。相反,它只是类中该字段的偏移量。是否field恰好是您的类中声明的第二个数据成员(包括任何祖先类中声明的任何内容)?如果是这样,那么这就解释了你从哪里得到 8。VMT 指针会得到 0,第一个字段会得到 4,依此类推,假设你的数据不超过 4 个字节,并且所有内容都对齐。

更改代码以从内存中读取值,如上面的代码行。那里可能允许也可能不允许该类型;即你可能只写offset field而不是offset SomeType.field.

于 2013-08-21T17:47:42.900 回答