2014-11-11 2 views
2

У меня есть рабочий IL код:MSIL».maxstack 1" выталкивает более чем на 1 значение

.method public hidebysig static void Main(string[] args) cil managed 
    { 
     .entrypoint 
     .maxstack 1 
     ldc.i4.s 10 
     ldc.i4.s 5 
     ldc.i4.s 15 
     ldc.i4.s 5 
     add 
     call void [mscorlib]System.Console::WriteLine(int32) 
     ret 
    } 

я поставил .maxstack 1 и подтолкнул 4 значения в стеке Eval. Почему это работает?

+2

Возможный дубликат [Почему директива .MaxStack необязательна в коде MSIL?] (Http://stackoverflow.com/questions/9846022/why-is-the-maxstack-directive-optional-in-msil-code) Короткий ответ заключается в том, что ваш код будет запущен, потому что он не проверяется по умолчанию. –

+1

Разве ваш образец кода не имеет несбалансированного стека? 'Add' будет появляться 15 и 5, нажимать 20, а затем вы выводите 20. Как насчет 10 и 5 вы нажали раньше? Куда они идут? – sisve

ответ

2

Спецификация CLI довольно непрозрачна в отношении предполагаемого использования директивы .maxstack. Некоторые намеки на то, что они предвидели необходимость в нем, но не прибили то, что должно быть точно. Мы можем получить некоторое представление о том, как он используется из источника дрожания, который включен в дистрибутив SSCLI20. Соответствующий код C++ в среде CLR/SRC/fjit/fjit.cpp:

/* set up the operand stack */ 
    size = methodInfo->maxStack+1; //+1 since for a new obj intr, +1 for exceptions 
#ifdef _DEBUG 
    size++; //to allow writing TOS marker beyond end; 
#endif 
    if (size > opStack_size) { 
     if (opStack) delete [] opStack; 
     opStack_size = size+4; //+4 to cut down on reallocations 
     New(opStack,OpType[opStack_size]); 
    } 

Обратите внимание на локоть комнате они оставляют, чтобы избежать необходимости повторно перераспределить структуру данных стека операндов, size+4 достаточно, чтобы объяснить свои наблюдения , Это не единственная причина, это также имеет значение, какой метод был задуман раньше, и если у него был большой .maxstack, тогда ничто не пойдет не так.

Fjit.cpp - это всего лишь образец реализации, поэтому не гарантируйте, что это работает так же, как в дрожании, которое вы используете. Но в противном случае достаточно, чтобы обеспечить понимание, директива заключается в том, чтобы помочь дрожанию избежать необходимости решать проблему с курицей и яйцом, вынуждая распределять структуру данных до, вставляя код. Это оптимизация.

1

Первое, что пришло на ум при чтении вашего вопроса, было то, что ассемблер, вероятно, использует крошечный заголовок метода (Partition II 25.4.2), отображая .maxstack спор.

IL-методу в модуле сразу предшествует заголовок метода, который поставляется в двух вариантах, жирных и крошечных. Если у метода нет локалей, нет обработчиков исключений, меньше 64 байтов IL и максимального стека 8 или меньше, тогда он может использовать крошечный заголовок. Крошечная заголовок не указывает .maxstack, а не какой-либо метод с крошечным заголовка предполагается иметь .maxstack из 8.

Если вы действительно хотите, чтобы проверить, что происходит, когда переполнение стека оценки, то вы должны обеспечить метод не использует крошечный заголовок, добавляя локальную переменную или обработчик исключений.

 Смежные вопросы

  • Нет связанных вопросов^_^