# Trying to understand the ethereum stack

I've been trying to understand the limits of the stack and how it works. It seems like the "Stack too deep" error only happens if there is an assembly block in the function. Without an assembly block, I have declared up to 27 uint variables with no problem.

``````uint one = 1;
uint two = 2;
uint three = 3;
uint four = 4;
.
.
.
uint twentyfive = 25;
uint twentysix = 26;
uint twentyseven = 27;
``````

However, if I add an assembly block, with the following simple operation, then I can't have more than 20 uint variables without getting the "Stack too deep" error.

``````assembly
{
let result := mul (5, 4)
}
``````

If I use uint variables in the MUL operation, then my limit drops to 19 uint variables in order to prevent the "Stack too deep" error.

``````assembly
{
let result := mul (five, four)
}
``````

Even with a long, complicated assembly operation, as long as there are no variables in it, I can have lots of uint variables declared. (Maybe this value is computed at compile-time.)

``````assembly
{
pop (mul (mul (mul (mul (mul (mul (mul (mul (1, 2), 3), 4), 5), 6), 7), 8), 9))
}
``````

But if I use one variable in the assembly operation, the limit drops to 10 uint variables, or else compilation fails with "Stack too deep".

``````assembly
{
pop (mul (mul (mul (mul (mul (mul (mul (mul (1, two), 3), 4), 5), 6), 7), 8), 9))
}
``````
1. Why is that? What is the relationship between variables declared in a function and the types of assembly operations that are performed in the function?
2. How many elements does the stack hold?
3. What size is each stack element? (32 bytes, I would assume.)
4. What is the stack used for?