Delphi中methodaddress的汇编代码解析

时间:2021-08-29 08:22:05

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   }  //获得方法的长度  //长度两个字节 指针4个字节  ///
        ADD     ESI,ECX                 { point ESI to next method      }  //指向下一个函数
        DEC     EDI
        JNZ     @@inner
@@parent:                              //获得父的方发表
        MOV     EAX,[EAX].vmtParent     { fetch parent vmt              }
        TEST    EAX,EAX                //是否为0 
        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]              //找到 并且得到指针 12 方法长度 3456 方法指针 7890 方法名称 7 方法名城的长度

@@exit:
        POP     EDI
        POP     ESI
        POP     EBX
end;

http://blog.csdn.net/diligentcatrich/article/details/8111297