我正在尝试学习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运行时如何知道应该将get_DefaultCredentials返回的值传递给set_Credentials,因为除了注释部分“ / 01000019 /”外似乎没有任何链接?
CLR如何在System.Net.WebRequest的当前实例上调用get_Proxy,即CIL代码中是否有一个指向实例编号的指针?
最佳答案
通常,它们在堆栈上传递-但请注意,这很大程度上是实现细节; p
1:构建堆栈,以使目标首先位于堆栈上=具体来说:
ldloc.0将请求加载到堆栈上
callvirt get_Proxy()消耗请求(因为是虚拟的),并将代理保留在堆栈上(从返回值开始)
调用get_DefaultCredentials()不会消耗任何东西,并附加默认凭据
callvirt set_Credentials使用2个值;第一个(代理)用作实例(自虚拟);第二个(凭据)用作第一个参数值
2:在这种情况下,实例保存在该方法的“本地”位置(即相对于堆栈帧的预留插槽);在这种情况下,位置0。最有可能使用“ dup”(根据需要复制参考),而不是使用stloc / ldloc。