我对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位。
答案 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
。