If you're asking why doesn't a compiler generate push instructions for local storage rather than direct manipulation of the stack pointer, it's a matter of efficiency.
Automatic variables (in C anyway) are uninitialized, so the code sequence would be (I'm going to use subl since I'm used to stacks growing down in memory):
C Code Actual assembly Your suggestion
void x(void) {
int a; subl 8,%esp push 0
int b; push 0
: : : blah blah blah blah
}
My answer is that it's unnecessary and inefficient in cases such as:
C Code Actual assembly Your suggestion
void x(void) {
int a[100]; subl 400,%esp push 0
push 0
push 0
: : :
push 0
: : : blah blah blah blah
What you propose may make sense for something like:
C Code Your suggestion
void x(void) {
int a = 7; push 7
int b = 9; push 9
int c[4]; subl 16,%esp
: : : blah blah
}