Как параметры передаются в вызовах функций в CIL? - PullRequest
3 голосов
/ 22 марта 2011

Я пытаюсь изучить 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 ''

В частности, я не могу понять следующие вещи в CILcode:

  1. Как среда выполнения CLR знает, что set_Credentials должна быть передана значение, возвращаемое из get_DefaultCredentials, поскольку, похоже, нет никакой ссылки, кроме прокомментированной части "/ 01000019 / "?

  2. Как CLR вызывает get_Proxy для текущего экземпляра System.Net.WebRequest, т. Е. Есть ли указатель на номер экземпляра в коде CIL?

Ответы [ 3 ]

2 голосов
/ 22 марта 2011

Как правило, они передаются в стеке, но обратите внимание, что это в значительной степени детали реализации; p

1: стек построен так, что цель находится в стекеfirst = конкретно:

  • ldloc.0 загружает запрос в стек
  • callvirt get_Proxy () принимает запрос (начиная с виртуального) и оставляет прокси в стеке (из возвращаемого значения)
  • call get_DefaultCredentials () ничего не использует и добавляет учетные данные по умолчанию
  • callvirt set_Credentials использует 2 значения;первый (прокси) используется как экземпляр (так как виртуальный);второе (учетные данные) используется в качестве первого значения параметра

2: в этом случае экземпляр хранится в «локальном» методе (т. е. зарезервированный слот относительно кадра стека).);в этом случае loc 0. В сборке релиза я действительно ожидал, что loc 0 будет удален, и все это будет обрабатываться просто без зарезервированных слотов;"dup" (для копирования ссылки по мере необходимости) скорее всего будет использоваться вместо stloc / ldloc.

1 голос
/ 22 марта 2011
  1. Инструкция call для IL_0012 помещает возвращаемое значение get_DefaultCredentials в стек, а метод set_Credentials в следующей строке передается в качестве аргумента в стек оценки.
  2. Переменная request, возвращаемая методом WebRequest.Create, сохраняется как локальная переменная с индексом 0 ( stloc.0 ) и затем загружается ldloc.0 , поэтому метод get_Proxy в строке IL_000d вызывается для этой переменной локальной переменной, которая была загружена в стек оценки.
0 голосов
/ 22 марта 2011

Это все на основе стека. Что происходит, так это то, что результат вызова метода, который возвращает значение get_DefaultCredentials, помещается в стек оценки.

Магической связи нет, значение просто находится на вершине стека.

Просто посмотрите на вызов конструктора, первое, что происходит, это то, что строка "http://www.costco.com" помещается поверх стека оценки. Тогда конструктор называется. Затем конструктор извлекает значения из стека оценки. Последнее значение, помещенное поверх стека, является последним параметром. ldstr помещает ровно одно значение на вершину стека. Результат вызова конструктора, который теперь является top , и эта ссылка затем извлекается и сохраняется в местоположении 0 stloc.0 (локальная переменная).

Вызов методов экземпляра немного отличается, первый аргумент в этом случае всегда является объектом, поэтому первый вызов, который вы видите здесь, это ldloc.0. Что толкает экземпляр объекта WebRequest поверх стека оценки. Отсюда мы вызываем get_Proxy методы, которые потребляют значение поверх стека оценки, помещенного туда ldloc.0, и возвращают возвращенный экземпляр объекта. Это эффективно заменяет значение в верхней части стека оценки. Однако теперь вершина стека больше не является значением, которое ldloc.0 помещает туда.

На самом деле ничего не передается, оно просто выдвигается и выталкивается, выключается и укладывается в стек.

...