zoukankan      html  css  js  c++  java
  • .NET 调用虚方法2 转

     在上一篇文章CLR怎样实现虚方法的多态调用(1)中主要介绍了CLR怎样多态调用虚方法以及各种类型的方法在Method Table中的排布,但是没有介绍怎样调用接口方法,当某个对象向上转型为接口时进行多态调用时,CLR是怎样实现的呢?以下面这段代码为例来说明:

    namespace Demo
    {
        public interface IFoo
        {
            void Foo();
        }
    
        public class Base : IFoo
        {
            public void Foo()
            {
                Console.WriteLine("In base's Foo function");
            }
        }
    
    
        class Program
        {
            static void Main(string[] args)
            {
                IFoo i = new Base();
                i.Foo();
            }
        }
    }

      在Essential .NET中,Don Box向读者简单描述了基于接口的多态调用,在堆中有一个全局接口映射表,当某个类实现了一个接口,就会在这个接口表中增加项,而增加的这些项又指向这个具体类的Method Table中的Method,可能说的不是太清楚,就用个图来表示:

    image

     当进行方法调用的时候,首先通过对象找到该类型的Method Table,根据偏移量找到指向Interface Offset Table的指针来定位这个Interface Offset Table,然后CLR查找调用方法在这个Offset Table的偏移量,最后调用该方法。调用的汇编代码如下:

     mov ecx, esi  -- 保存对象地址到ecx中

     mov eax, dword ptr [ecx] -- 把类型的Method Table的地址保存在eax中

     mov eax, dword ptr [eax+0ch] -- 把Interface Offset Table的地址保存在eax中

     mov eax, dword ptr [eax + interface offset] -- 根据Interface在Table中的偏移量,找到其地址并保存到eax中

     call dword ptr [eax +  method offset] -- 根据该方法的偏移量定位改方法进行调用

    可以说这样的调用逻辑是很清楚容易让人理解的。

    但是当我用windbg进行跟踪的时候却发现接口方法调用机制和上面所说的不同,并没有一个查找Interface Offset Table的过程,在Main函数里是这样的调用:

     mov ecx, esi --  保存对象地址到ecx中

     call dword ptr ds:[980010h]  在数据段980010h上保存的是一个指针,实际上调用的是:

     jmp mscorwks!ResolveWorkerAsmStub

     可以看到跳转到ResolveWorkerAsmStub函数里去了。而这个函数是做什么的呢,下面的代码是从SSCLI里面找到的(有兴趣的可以看看virtualcallstubcpu.hpp):

    __declspec (naked) void ResolveWorkerAsmStub()

    {

    // 首先保存寄存器状态

    call VirtualCallStubManager::ResolveWorkerStatic //调用ResolveWorkerStatic方法
    //还原寄存器状态
    jmp eax //eax保存着实际上要调用的方法的地址,所以这里就开始了方法调用

    }

    所以猜想到在VirtualCallStubManager::ResolveWorkerStatic函数里面正确找到了方法的地址,保存在eax里。

    看来到底是怎样取到该方法地址这个问题只能等下次有时间再用windbg跟踪。如果有人了解,也希望能解释一下来帮助我解答疑惑。

  • 相关阅读:
    Android自定义属性,format详解
    设置EditText是否可编辑
    Android中Application设置全局变量以及传值
    android:ellipsize属性的含义
    Java集合框架List,Map,Set等全面介绍
    二十款漂亮的CSS字体样式,让你受用非浅
    IE浏览器不见了
    display属性值:
    用CSS设置多个背景、背景渐变、指定背景大小
    [转]IE6双倍边距——IE布局BUG集锦
  • 原文地址:https://www.cnblogs.com/qianyz/p/2774792.html