大难题,求助大家!(300分)

  • 主题发起人 主题发起人 LeoWang
  • 开始时间 开始时间
L

LeoWang

Unregistered / Unconfirmed
GUEST, unregistred user!
我没辙了,看了很久,没有明白,只好来请教高人!
procedure TObject.Dispatch(var Message);
class function TObject.MethodAddress(const Name: ShortString): Pointer;
procedure GetDynaMethod;

这三个是关于tobject类的函数,处理函数指针的【我个人以为哦】
我对汇编语言也不是很了解,本来多加分数的,可论坛只能加到300分,请大家
来帮忙了,谢了先!

procedure GetDynaMethod;
{ function GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer; }
asm
{ -> EAX vmt of class }
{ BX dynamic method index }
{ <- EBX pointer to routine }
{ ZF = 0 if found }
{ trashes: EAX, ECX }

PUSH EDI
XCHG EAX,EBX
JMP @@haveVMT
@@outerLoop:
MOV EBX,[EBX]
@@haveVMT:
MOV EDI,[EBX].vmtDynamicTable
TEST EDI,EDI
JE @@parent
MOVZX ECX,word ptr [EDI]
PUSH ECX
ADD EDI,2
REPNE SCASW
JE @@found
POP ECX
@@parent:
MOV EBX,[EBX].vmtParent
TEST EBX,EBX
JNE @@outerLoop
JMP @@exit

@@found:
POP EAX
ADD EAX,EAX
SUB EAX,ECX { this will always clear the Z-flag ! }
MOV EBX,[EDI+EAX*2-4]

@@exit:
POP EDI
end;
procedure TObject.Dispatch(var Message);
asm
PUSH EBX
MOV BX,[EDX]
OR BX,BX
JE @@default
CMP BX,0C000H
JAE @@default
PUSH EAX
MOV EAX,[EAX]
CALL GetDynaMethod
POP EAX
JE @@default
MOV ECX,EBX
POP EBX
JMP ECX

@@default:
POP EBX
MOV ECX,[EAX]
JMP dword ptr [ECX].vmtDefaultHandler
end;


class function TObject.MethodAddress(const Name: ShortString): Pointer;
asm
{ -> EAX Pointer to class }
{ EDX Pointer to name }
PUSH EBX
PUSH ESI
PUSH EDI
XOR ECX,ECX
XOR EDI,EDI
MOV BL,[EDX]
JMP @@haveVMT
@@outer: { upper 16 bits of ECX are 0 ! }
MOV EAX,[EAX]
@@haveVMT:
MOV ESI,[EAX].vmtMethodTable
TEST ESI,ESI
JE @@parent
MOV DI,[ESI] { EDI := method count }
ADD ESI,2
@@inner: { upper 16 bits of ECX are 0 ! }
MOV CL,[ESI+6] { compare length of strings }
CMP CL,BL
JE @@cmpChar
@@cont: { upper 16 bits of ECX are 0 ! }
MOV CX,[ESI] { fetch length of method desc }
ADD ESI,ECX { point ESI to next method }
DEC EDI
JNZ @@inner
@@parent:
MOV EAX,[EAX].vmtParent { fetch parent vmt }
TEST EAX,EAX
JNE @@outer
JMP @@exit { return NIL }

@@notEqual:
MOV BL,[EDX] { restore BL to length of name }
JMP @@cont

@@cmpChar: { upper 16 bits of ECX are 0 ! }
MOV CH,0 { upper 24 bits of ECX are 0 ! }
@@cmpCharLoop:
MOV BL,[ESI+ECX+6] { case insensitive string cmp }
XOR BL,[EDX+ECX+0] { last char is compared first }
AND BL,$DF
JNE @@notEqual
DEC ECX { ECX serves as counter }
JNZ @@cmpCharLoop

{ found it }
MOV EAX,[ESI+2]

@@exit:
POP EDI
POP ESI
POP EBX
end;
 
Delphi语言里面,
计算类的成员函数地址的函数?
不过这样没有上下文没头没脑的偶也看不懂哦。
TObject是Delphi所有类的根,
这三个可能是做动态联编Dynamic Binding....类似功能吧

不乱讲了
等高手来re吧
 
只能给你添点注释了~~~

procedure TObject.Dispatch(var Message);
class function TObject.MethodAddress(const Name: ShortString): Pointer;
procedure GetDynaMethod;

这三个是关于tobject类的函数,处理函数指针的【我个人以为哦】
我对汇编语言也不是很了解,请大家
来帮忙了,谢了先!
//好像是delphi中的VCL源程序吗!
procedure GetDynaMethod;
{ function GetDynaMethod(vmt: TClass; selector: Smallint) : Poi

nter; }
asm
{ -> EAX vmt of class } ;->表示入口参数
{ BX dynamic method index } ;<-表示出口参数
{ <- EBX pointer to routine }
{ ZF = 0 if found }
{ trashes: EAX, ECX }
PUSH EDI
XCHG EAX,EBX ;EAX,EBX内容交换一下
;EBX是类的Virtual Method Table了
;EAX是虚拟方法的索引了
JMP @@haveVMT ;//跳转判断是否有虚拟函数表
@@outerLoop:
MOV EBX,[EBX]
@@haveVMT:
MOV EDI,[EBX].vmtDynamicTable ;是一个结构了
TEST EDI,EDI
JE @@parent ;如果EDI为零应该是的,那么找父类的虚拟函
数表
MOVZX ECX,word ptr [EDI] ;非零说明有vmt,并把值覆给Ecx
PUSH ECX
ADD EDI,2
REPNE SCASW
JE @@found ;这一段好像是在查找EAX中的内容是否有,
;EAX是索引,究竟这个索引是函数地址,行是1,23,4
,
;不知道
POP ECX
@@parent: ;没有找到那到父类中去找吧
MOV EBX,[EBX].vmtParent
TEST EBX,EBX
JNE @@outerLoop
JMP @@exit
@@found: ;找到了把routine地址付给EBX吧
POP EAX
ADD EAX,EAX
SUB EAX,ECX { this will always clear the Z-flag ! }
MOV EBX,[EDI+EAX*2-4]
@@exit:
POP EDI
end;
;下面也是差不多的,
TEST ESI,ESI
JE @@parent
MOV DI,[ESI] { EDI := method count }
ADD ESI,2
@@inner: { upper 16 bits of ECX are 0 ! }
MOV CL,[ESI+6] { compare length of strings }
CMP CL,BL
JE @@cmpChar
@@cont: { upper 16 bits of ECX are 0 ! }
MOV CX,[ESI] { fetch length of method desc }
ADD ESI,ECX { point ESI to next method }
DEC EDI
JNZ @@inner
@@parent:
MOV EAX,[EAX].vmtParent { fetch parent vmt }
TEST EAX,EAX
JNE @@outer
JMP @@exit { return NIL }
@@notEqual:
MOV BL,[EDX] { restore BL to length of name }
JMP @@cont
@@cmpChar: { upper 16 bits of ECX are 0 ! }
MOV CH,0 { upper 24 bits of ECX are 0 ! }
@@cmpCharLoop:
MOV BL,[ESI+ECX+6] { case insensitive string cmp }
XOR BL,[EDX+ECX+0] { last char is compared first }
AND BL,$DF
JNE @@notEqual
DEC ECX { ECX serves as counter }
JNZ @@cmpCharLoop
{ found it }
MOV EAX,[ESI+2]
@@exit:
POP EDI
POP ESI
POP EBX
end;
 
在你申明一个消息过程如:procedure MyMsgHandler(var Msg :Message) ;message WM_XXX;
以后,如果能够成功编译的话,编译器将为你做一个类似于函数表的东西(vmt??),想象
成下面这个样子吧:
id function_address
wm_xxx MyMsgHandler
... .....

每个类有自己的vmt的入口地址,同时这个入口地址向上偏移36字节就是其父类的vmt的入口
地址。。。。这样从一个类你可以追索到它的所有基础类(想象一下如果有多重继承或vcl是
个森林而不是个树的情况,哈哈)。
那么现在可以明白dispatch是做什么的了,先在类本身的vmt中找到该消息的处理函数,如果
没有的话就得到上一级父类的vmt,然后再找,直到找到TObject的vmt,如果还是没有的话,
会给你一个缺省处理函数来处理(其实就是什么也不作)。。。

我也只看懂这么多,有兴趣大家深入讨论。。。。
 
有点明白了,再摸索摸索可能就通了,
多谢各位的帮助!
 
咳!!什么时候的东西,当时没有看到,来晚了!光这3个函数就可以写半本书的,它涉及到
Delphi的对象模型,很重要的。不知道你现在懂了波?没懂我可能还有机会赚这个分罗![:)][:)]
 

Similar threads

I
回复
0
查看
773
import
I
A
回复
0
查看
1K
Andreas Hausladen
A
I
回复
0
查看
739
import
I
I
回复
0
查看
535
import
I
I
回复
0
查看
805
import
I
后退
顶部