参数如何在CIL函数调用中传递?
我想学习CIL代码,但不能去除和如何返回一个函数的值作为参数传递给另一个函数。对于下面的函数参数如何在CIL函数调用中传递?
我已经生成的CIL代码:
public bool TestWebPage()
{
WebRequest request = WebRequest.Create("http://www.costco.com");
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
}
CIL代码:
//000021: public void TestWebPage()
//000022: {
IL_0000: /* 00 | */ nop
.line 23,23 : 7,71 ''
//000023: WebRequest request = WebRequest.Create("http://www.costco.com");
IL_0001: /* 72 | (70)000001 */ ldstr "http://www.costco.com" /* 70000001 */
IL_0006: /* 28 | (0A)000012 */ call class [System/*23000003*/]System.Net.WebRequest/*01000016*/ [System/*23000003*/]System.Net.WebRequest/*01000016*/::Create(string) /* 0A000012 */
IL_000b: /* 0A | */ stloc.0
.line 24,24 : 7,70 ''
//000024: request.Proxy.Credentials = CredentialCache.DefaultCredentials;
IL_000c: /* 06 | */ ldloc.0
IL_000d: /* 6F | (0A)000013 */ callvirt instance class [System/*23000003*/]System.Net.IWebProxy/*01000017*/ [System/*23000003*/]System.Net.WebRequest/*01000016*/::get_Proxy() /* 0A000013 */
IL_0012: /* 28 | (0A)000014 */ call class [System/*23000003*/]System.Net.ICredentials/*01000019*/ [System/*23000003*/]System.Net.CredentialCache/*01000018*/::get_DefaultCredentials() /* 0A000014 */
IL_0017: /* 6F | (0A)000015 */ callvirt instance void [System/*23000003*/]System.Net.IWebProxy/*01000017*/::set_Credentials(class [System/*23000003*/]System.Net.ICredentials/*01000019*/) /* 0A000015 */
IL_001c: /* 00 | */ nop
.line 25,25 : 7,73 ''
具体来说,我无法理解在CIL代码以下的事情:
CLR运行时如何知道set_Credentials要传递从get_Defa返回的值ultCredentials,因为除了注释部分“/ /”之外似乎没有任何链接。
CLR如何在System.Net.WebRequest的当前实例上调用get_Proxy,即在CIL代码中是否存在指向实例编号的指针?
通常,它们被传递到堆栈 - 但请注意,这在很大程度上是一个实现细节; p
1:叠层被建立起来,使得目标是在堆栈上第一=具体:
- ldloc.0负载请求到堆栈
- callvirt get_Proxy()消耗请求(因为虚拟)和离开堆叠上的代理(从返回值)
- call get_DefaultCredentials()不消耗任何东西,并追加默认凭据
- callvirt set_Credentials消耗2个值;第一个(代理)被用作实例(因为虚拟);第二(凭证)被用作所述第一参数值
2:在这种情况下,实例在“本地”保持在方法(即保留相对于堆栈帧中的时隙);在这种情况下,loc 0.在发布版本中,我实际上期望删除loc 0,并且这一切都是在没有预留插槽的情况下处理的; “dup”(根据需要复制引用)最有可能被使用,而不是stloc/ldloc。
它都是基于堆栈的。会发生什么情况是将调用返回值get_DefaultCredentials
的方法的结果推送到评估堆栈。
没有什么神奇的链接,该值恰好驻留在堆栈的顶部。
试想一下,在构造函数调用,这种情况发生的第一件事就是该字符串"http://www.costco.com"
是在顶部的评价压入堆栈。然后调用构造函数。构造函数然后弹出评估堆栈的值。推到栈顶的最后一个值是最后一个参数。 ldstr
只在堆栈顶部推送一个值。构造函数调用的结果也就是现在的顶部,然后将该参考被弹出并存储在位置0 stloc.0
(局部变量)。
调用实例的方法略有不同,在这种情况下,第一个参数始终是对象,以便你在这里看到的第一个电话是ldloc.0
。这将WebRequest
对象实例推到评估堆栈的顶部。从这里我们称之为get_Proxy
方法,它消耗在上面的数值计算堆栈由ldloc.0
放在那里,并返回返回的对象实例。这实际上取代了评估堆栈顶部的值。然而,现在堆栈的顶端不再是ldloc.0
放在那里的值。
都没有真正被传递,它只是推入与弹出,关闭和堆栈。