Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculation of maxstack value in IL code

Tags:

stack

c#

cil

il

ildasm

I have following program to add the values. When I am comenting Add method call in main method and looking into ILDASM.EXE Maxstack size is 2. And after uncommenting maxstack size becomes 4.

Why in the case of Main method all variables are not going into stack as stack size remains 2 only, While in case of Add method call every variable goes into stack? Is this the case that inside main method calculation is happening one by one so that it takes only two variable at a time.

Please clear my confusion.

static void Main(string[] args)
{
    int x = 2;
    int y = 3;
    int a = 4;
    int b = 5;
    int c = 6;

    Console.WriteLine(x + y + a + b + c);
    Console.WriteLine(Add(10, 20, 30, 40));
    Console.ReadLine();
}

static int Add(int x, int y, int z, int a)
{
    return x + y + z + a;
}
like image 422
Manjay_TBAG Avatar asked Nov 27 '15 07:11

Manjay_TBAG


People also ask

How is stack value calculated?

Count the number of complete strings, multiply by 8 (since "STACK---" is 8 bytes long), and you have the number of bytes of remaining stack space.


1 Answers

Each variable initialization:

int x = 2;

Will require the value to be on the stack: (stack size: 1 required so far)

.locals init ([0] int32 x,
       [1] int32 y,
       [2] int32 a,
       [3] int32 b,
       [4] int32 c)
IL_0000:  ldc.i4.2  // push 2 to the stack
IL_0001:  stloc.0   // load local variable 0 from stack ( x = 2 )

These operations happen sequentially, therefore max stack size required is still 1, during:

int y = 3;
int a = 4;
int b = 5;
int c = 6;

And when it comes to this:

Console.WriteLine(x + y + a + b + c);

To add any two variables, a stack size of 2 is required:

IL_000b:  ldloc.0 // copy to stack x, max stack size required is still 1.
IL_000c:  ldloc.1 // copy to stack y, max stack size required is 2 now.
IL_000d:  add     // execute add, will cause the sum x + y to be on stack
IL_000e:  ldloc.2 // copy to stack a
IL_000f:  add     // execute add... (adds a to the result of x + y)
....

The differential IL when you uncomment the Add method is below.

When calling a method, you need to push the instance reference onto the stack (meaning, if the Add method had been non-static, the instance pointer to its declaring type should be pushed onto the stack)

Then, each argument that needs to be passed to the method should also be pushed onto the stack.

Therefore, it is the number of parameters of the Add method in your case which defines the max stack size. Add a parameter to this Add method, and you will see that the max stack size will increase to 5:

// method is static so no need to push an instance pointer to the stack
IL_001a:  ldc.i4.s   10 // push to stack
IL_001c:  ldc.i4.s   20 // push to stack
IL_001e:  ldc.i4.s   30 // push to stack
IL_0020:  ldc.i4.s   40 // push to stack
IL_0022:  call       int32 Program::Add(int32,
                                      int32,
                                      int32,
                                      int32)
IL_0027:  call       void [mscorlib]System.Console::WriteLine(int32)
like image 83
Oguz Ozgul Avatar answered Sep 19 '22 23:09

Oguz Ozgul