为什么我的内联不能达到我的预期?

时间:2013-08-21 17:29:04

标签: freepascal

我对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)将向我报告{42}在第42行中分配了i(看到上面的行编号。)

我缺少内联汇编的内容吗?

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

更新:我想我可能会定位到64位。

1 个答案:

答案 0 :(得分:6)

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

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

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

我想你会发现它不是。如果Free Pascal解释此代码the same way Delphi does,则对field的裸引用不包括隐式Self部分。相反,它只是该类中该字段的偏移量field碰巧是您的类中声明的第二个数据成员(包括在任何祖先类中声明的任何内容)吗?如果是这样,那就解释了你从哪里获得8。 VMT指针为0,第一个字段为4,依此类推,假设您没有大于4个字节,并且所有内容都已对齐。

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