读VCL源码的第1000个问题!----- 汇编厉害的虾来解释一下这个代码! (100分)

  • 主题发起人 taozhiyu
  • 开始时间
T

taozhiyu

Unregistered / Unconfirmed
GUEST, unregistred user!
class function TObject.ClassName: ShortString;
{$IFDEF PUREPASCAL}
begin
Result := PShortString(PPointer(Integer(Self) + vmtClassName)^)^;
end;
{$ELSE}
asm
{ -> EAX VMT }
{ EDX Pointer to result string }
PUSH ESI
PUSH EDI
MOV EDI,EDX
MOV ESI,[EAX].vmtClassName
XOR ECX,ECX
MOV CL,[ESI]
INC ECX
REP MOVSB
POP EDI
POP ESI
end;
{$ENDIF}


class function TObject.ClassNameIs(const Name: string): Boolean;
{$IFDEF PUREPASCAL}
var
Temp: ShortString;
I: Byte;
begin
Result := False;
Temp := ClassName;
for I := 0 to Byte(Temp[0]) do
if Temp <> Name then Exit;
Result := True;
end;
{$ELSE}
asm
PUSH EBX
XOR EBX,EBX
OR EDX,EDX
JE @@exit
MOV EAX,[EAX].vmtClassName
XOR ECX,ECX
MOV CL,[EAX]
CMP ECX,[EDX-4]
JNE @@exit
DEC EDX
@@loop:
MOV BH,[EAX+ECX]
XOR BH,[EDX+ECX]
AND BH,0DFH
JNE @@exit
DEC ECX
JNE @@loop
INC EBX
@@exit:
MOV AL,BL
POP EBX
end;
{$ENDIF}
 
居然还有汇编......听课好了...[:D][:D]
 
ESI是什么?寄存器?
 
为什么非要理解汇编呢?不是指明了:如果是采用PASCAL如何,如果使用汇编又如何,直接理解PASCAL就可以了!
 
class function TObject.MethodName(Address: Pointer): ShortString;
asm
{ -> EAX Pointer to class }
{ EDX Address }
{ ECX Pointer to result }
PUSH EBX
PUSH ESI
PUSH EDI
MOV EDI,ECX
XOR EBX,EBX
XOR ECX,ECX
JMP @@haveVMT
@@outer:
MOV EAX,[EAX]
@@haveVMT:
MOV ESI,[EAX].vmtMethodTable { fetch pointer to method table }
TEST ESI,ESI
JE @@parent
MOV CX,[ESI] /// vmt中条目的个数,初始化ecx,ecx这里作为循环计数器 , 因为是两个字节,所以用move cx, [esi],而不是move ecx,[esi]
ADD ESI,2 /// vmt 偏移头两个字节是整个vmt的条目数,是一个smallint,所以是+2
@@inner:
CMP EDX,[ESI+2] // 比较传入参数和vmt中第一个条目的指向的值,就是一个published的函数的地址
JE @@found
MOV BX,[ESI] // 取得下一个条目的偏移量
ADD ESI,EBX // 取得下一个条目的偏移地址
DEC ECX //// 计数器 减一
JNZ @@inner
@@parent:
MOV EAX,[EAX].vmtParent
TEST EAX,EAX
JNE @@outer
MOV [EDI],AL /// 返回空字符串
JMP @@exit

@@found:
ADD ESI,6 // 指向的函数的名字
XOR ECX,ECX
MOV CL,[ESI] /// 所有字符的长度,不包括pacal string的起始字符,其实字符是标识整个字符串长度用的
INC ECX /// 初始化下一个copy字符串指令循环的循环次数
REP MOVSB /// copy 结果字符串,rep指令执行的次数是ecx的值

@@exit:
POP EDI
POP ESI
POP EBX
end;
以前看的记录,不知道对不对,如果对的话,那么和你的问题应该大同小易吧?!
 
class function TObject.ClassName: ShortString;
{$IFDEF PUREPASCAL}
begin
Result := PShortString(PPointer(Integer(Self) + vmtClassName)^)^;
end;
{$ELSE}
asm
{ -> EAX VMT }
{ EDX Pointer to result string }
PUSH ESI
PUSH EDI
MOV EDI,EDX
{ EDI := DEX
EDX為指向一個內存位置, 用來存放返回結果, 即類的名稱字符串
在指定給EDI, 是用準備給另一個匯編指令 -- REP MOVSB --所使用 }
MOV ESI,[EAX].vmtClassName
{ ESI := Pointer(EAX + vmtClassName)^;
EAX指向VMT的內存起始位置, 尚它加上徧移量vmtClassName(定義在 System中的常量, 為 -44)
取到為一個指向shortstring的位置, 其中存放著類的名稱字符串, 如 'TForm1'}
XOR ECX,ECX // ECX := 0;
MOV CL,[ESI]
{ ESI為指向類的名稱字符串位內存位置, 因其型態為TShortString, 所以第一Byte
為字符串長度, 故此動作是將字符串長度設定到ECX中 }
INC ECX // Inc(ECX);
{ 因為底下的 REP MOVSB 會從ESI複製ECX個Bytes到EDI中
ESI 目前指向類名稱字符串,
EDI 指向存放傳回結果的位置,
ECX 為名稱字符串長度, 將ECX加一, 是因TShortString的第一個
Byte(存放字串長度) 也要考慮進去 }
REP MOVSB
POP EDI
POP ESI
end;
{$ENDIF}

....
太多了懶得回答, 有空再回覆
 
esi是寄存器,一般用于指针(si你知道吧,那是16位的,加个e就是32位,其他寄存器也是,比如eax,ebx之类)
ClassName这个函数就是就是拷贝几个字符罢了
 
Good,路还很长![:D]
 
顶部