Local Variables 

We have known how to use stack as an interface for passing parameters to the subroutine. The idea is to use BP register as an anchor point to access the passed parameters using instructions like mov r/m, [BP + n].

When a subroutine is invoked, a new environment is created. In his newly created environment, new local variables are defined, while the values of the previous environment must be preserved. Variables for holding intermediate values during a computation like expression evaluation may also be needed. Like return addresses, these local variables are dynamic data whose values must be preserved over the lifetime of the procedure, but not beyond its termination. At the termination of the procedure, the current environment disappears and the previous environment must be restored.

Space for local variables can be reserved by subtracting the required number of bytes from SP.
Since the portion of the stack holding local variables is at a lower address than BP, negative offsets from BP are used to address local variables.

In the following example, assume that the size of char is 2 bytes, the size of int is 4 bytes, STDCALL convention is used.

Pseudo-code (Java-like)Assembly Language
void Test(char i, char j){
char b;
int k;
k = 9;
b = i;
_Test PROC
push BP
mov BP, SP
sub SP, 6
push AX
mov DWORD PTR [BP - 6], 9
mov AX, [BP + 4]
mov [BP - 2], AX
pop AX
mov SP, BP
pop BP
ret 4
_Test ENDP