程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> CLR怎樣實現虛方法的多態調用(2)

CLR怎樣實現虛方法的多態調用(2)

編輯:關於.NET

在上一篇文章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,可能說的不是太清楚,就用個圖來表示:

當進行方法調用的時候,首先通過對象找到該類型的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跟蹤。如果有人了解,也希望 能解釋一下來幫助我解答疑惑。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved