13

I am learning assembly language in my spare time. Can anyone explain why .maxstack appears to be optional in this program. I have tried to find the answer online and in my book with no such luck i.e. the program will compile and run with .Maxstack commented out:

//Add.il
//Add Two Numbers

.assembly extern mscorlib {}

.assembly Add
{
    .ver 1:0:1:0
}
.module add.exe

.method static void main() cil managed
{
    //.maxstack 2
    .entrypoint

    ldstr "The sum of 50 and 30 is = "
    call void [mscorlib]System.Console::Write (string)

    ldc.i4.s 50
    ldc.i4 30    
    add
    call void [mscorlib]System.Console::Write (int32)
    ret
}

I am compiling the program at the command line using the ILASM tool and then running the generated executeable.

mdb
  • 52,000
  • 11
  • 64
  • 62
w0051977
  • 15,099
  • 32
  • 152
  • 329

2 Answers2

14

I think your confusion stems from a misunderstanding of what .maxstack actually does. It's an easy mistake to make, because it seems like it would cause an error when executing. Surprisingly, that particular directive actually has nothing do with the with stack size at runtime, instead, it is specifically used during code verification.

From Partition III - Section 1.7.4

Note: Maxstack is related to analysis of the program, not to the size of the stack at runtime. It does not specify the maximum size in bytes of a stack frame, but rather the number of items that must be tracked by an analysis tool.

The code becomes unverifiable. That same section, notes that any conforming implementation need not support a method with an invalid max stack value. However, it doesn't say that it must not, and quite clearly, the runtime is executing the code. So if it seems to have no effect, why even bother having it?

Believe it or not, by default, the .NET framework runs unverifiable code. It was actually difficult for me to figure out how to enable verification in .NET 4.0, but if you do turn on CAS, your program (with .maxstack 1) will stop running with

Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program. at main()

Keeping this in mind, unverifiable the code cannot run in any environment that doesn't have full trust (generally assemblies from the internet). If that's not important to you, you can let it be an invalid value, and it really won't make a difference. If the code itself is still correct, it will run fine; of course if there is an actually an issue with the IL stack, it will throw an InvalidProgramException.

Christopher Currens
  • 29,917
  • 5
  • 57
  • 77
0

If I recall correctly, the default stack size is 8 if the statement is omitted.

  • 1
    this is what I first thought, but the program still runs if I set the .maxstack in the above program to 1. It should be 2 or above for the program from what I can see. – w0051977 Mar 23 '12 at 20:34
  • Just guessing here, but perhaps ILASM is clever enough to realize that 1 would not be enough and overrides the setting. – 500 - Internal Server Error Mar 23 '12 at 20:37
  • 2
    @500-InternalServerError, it's not. According to ILDASM, the emited code actually does contain `.maxstack 1`. And according to the specification, such code should be invalid and unverifiable. And PEVerify actually fails verification of the assembly. But it runs fine anyway. – svick Mar 23 '12 at 21:09
  • @w0051977, because then the default size of 8 is used, as 500 pointed out. You can verify this by using ildasm. – svick Mar 23 '12 at 21:18
  • @w0051977 what you have to remember, of course, is that .NET isn't actually executing IL but compiles into native code and the resulting native code might not need any storage allocated to perform the operations that correspond to the IL code. – 500 - Internal Server Error Mar 23 '12 at 22:13
  • 1
    That's the same as when you set it to 1: it's not verifiable code, but it does run, because it seems .Net actually doesn't need the value. – svick Mar 23 '12 at 22:13
  • I know of no such reference. I seem to recall that Serge Lidin discussed the setting in his ILASM books, but in the toy compilers that I've written for .NET maxstack has never been an issue (I've never emitted anything complex enough to blow through the 8 default entries). – 500 - Internal Server Error Mar 23 '12 at 22:54
  • Internal Server Error, I am setting the value to 0 and it is still working. I am not using the default value of 8. – w0051977 Mar 24 '12 at 10:37