占个沙发, protected里的函数或过程知道怎么调用,Private里的东东,以下代码希望给你一些启发,我相信不能完全帮你解决问题请注意,一定是这种情况,如果其中任何一项位置发生变化,都不可行 之所以这么说, 1.这种情况下GetValue及SetValue的入口地址在类信息中是绝对没有保存的,调用指令是 CALL 偏移值 2.如果节点发生改变,如GetValue函数在protected/published节点中,那么这个函数的地址会保存在类信息中,调用指令会变成 CALL DWORD PTR [REG + Offset] REG=类地址,Offset=vm位置 这种情况的调用不在本讨论范围,另外讨论, TMyClass = TObject private Function GetValue : integer; procedure SetValue(Value : integer); public Property Value : integer read GetValue write SetValue; end;//另一个单元里面这么处理 procedure TMyClass_Value_ReadWrite; begin TMyClass(NIL).Value := TMyClass(NIL).Value; end;//通过这个函数配合以上过程得到Private节里GetValue函数和SetValue过程的地址 Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer; var P : PChar; i : integer; begin Result := NIL; P := ReadWriteAdr; for i:=0 to 100 do begin if P^ = #$E8 then begin GetSecondCall := not GetSecondCall; if GetSecondCall then begin Result := Ptr(integer(P+5) + Pinteger(P+1)^); Break; end; end; inc(P); end; end;//调用TMyClass.GetValue函数 Function CallTMyClass_GetValue(Obj : TMyClass) : integer; var PGet : Pointer; begin PGet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , False); asm MOV EAX , Obj; CALL P; MOV Result , EAX; end; end;//调用TMyClass.SetValue函数 procedure CallTMyClass_GetValue(Obj : TMyClass; NewValue : integer); var PSet : Pointer; begin PSet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , True); asm MOV EAX , Obj; MOV EDX , NewValue; //MOV ECX , 被调函数的第2个参数 //PUSH 被调函数的第3个参数 and more. CALL P; end; end; D7下直接剪的我一个工程里的部分代码,没单独编译测试,希望对你有所启发, 我目前的知识,有些private里的过程正常情况是不容易得到地址的,这是Delphi编译器的自己的限制,编译时每编译一个函数,会形成一个地址表,在遇到函数调用的代码时查表得到地址,而对Private里的过程,被编译器故意隔离在本单元之外, 如果给你出这个题的人,是想考验你对编译器的研究有多深的话,那就真的很恶心了 如果编译器开关里有这么一个开关,允许放开的话,那这就简单了
Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer; var P : PChar; i : integer; begin Result := NIL; P := ReadWriteAdr; for i:=0 to 100 do begin if P^ = #$E8 then begin GetSecondCall := not GetSecondCall; if GetSecondCall then begin Result := Ptr(integer(P+5) + Pinteger(P+1)^); Break; end; inc(P,4); //漏了这一行 end; inc(P); end; end;
protected里的函数或过程知道怎么调用,Private里的东东,以下代码希望给你一些启发,我相信不能完全帮你解决问题请注意,一定是这种情况,如果其中任何一项位置发生变化,都不可行
之所以这么说,
1.这种情况下GetValue及SetValue的入口地址在类信息中是绝对没有保存的,调用指令是 CALL 偏移值
2.如果节点发生改变,如GetValue函数在protected/published节点中,那么这个函数的地址会保存在类信息中,调用指令会变成 CALL DWORD PTR [REG + Offset] REG=类地址,Offset=vm位置
这种情况的调用不在本讨论范围,另外讨论,
TMyClass = TObject
private
Function GetValue : integer;
procedure SetValue(Value : integer);
public
Property Value : integer read GetValue write SetValue;
end;//另一个单元里面这么处理
procedure TMyClass_Value_ReadWrite;
begin
TMyClass(NIL).Value := TMyClass(NIL).Value;
end;//通过这个函数配合以上过程得到Private节里GetValue函数和SetValue过程的地址
Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer;
var
P : PChar;
i : integer;
begin
Result := NIL;
P := ReadWriteAdr;
for i:=0 to 100 do begin
if P^ = #$E8 then begin
GetSecondCall := not GetSecondCall;
if GetSecondCall then begin
Result := Ptr(integer(P+5) + Pinteger(P+1)^);
Break;
end;
end;
inc(P);
end;
end;//调用TMyClass.GetValue函数
Function CallTMyClass_GetValue(Obj : TMyClass) : integer;
var
PGet : Pointer;
begin
PGet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , False);
asm
MOV EAX , Obj;
CALL P;
MOV Result , EAX;
end;
end;//调用TMyClass.SetValue函数
procedure CallTMyClass_GetValue(Obj : TMyClass; NewValue : integer);
var
PSet : Pointer;
begin
PSet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , True);
asm
MOV EAX , Obj;
MOV EDX , NewValue;
//MOV ECX , 被调函数的第2个参数
//PUSH 被调函数的第3个参数 and more.
CALL P;
end;
end;
D7下直接剪的我一个工程里的部分代码,没单独编译测试,希望对你有所启发,
我目前的知识,有些private里的过程正常情况是不容易得到地址的,这是Delphi编译器的自己的限制,编译时每编译一个函数,会形成一个地址表,在遇到函数调用的代码时查表得到地址,而对Private里的过程,被编译器故意隔离在本单元之外,
如果给你出这个题的人,是想考验你对编译器的研究有多深的话,那就真的很恶心了
如果编译器开关里有这么一个开关,允许放开的话,那这就简单了
Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer;
var
P : PChar;
i : integer;
begin
Result := NIL;
P := ReadWriteAdr;
for i:=0 to 100 do begin
if P^ = #$E8 then begin
GetSecondCall := not GetSecondCall;
if GetSecondCall then begin
Result := Ptr(integer(P+5) + Pinteger(P+1)^);
Break;
end;
inc(P,4); //漏了这一行
end;
inc(P);
end;
end;
TFakeForm = class(TForm2);调用时
TFakeForm(Form2).Test;这样做是没问题的.但是如果是private的话,我想只能3楼那样,通过偏移量来调用了.具体可以参考一下
http://www.delphibbs.com/keylife/iblog_show.asp?xid=7198
跨单元、跨类地访问Delphi类的私有域