Stack Frames

Stack frames are used for creating an area to store local variables in a function. This is how many programming languages set up functions.

+-----------------+ -+
|                 |  |
| Local Variables |  |
|                 |  |-----Some other function
+-----------------+  |
| Return Address  |  |
+-----------------+  |
| Function Args   | -+
+-----------------+ 
| Local Variables | -+
|                 |  |
+-----------------+  +-----Main Function
| Return Address  |  |
+-----------------+  |
| Function args   |  |
+-----------------+ -+

From the caller, you first push your arguments to the stack. Then you call the address of the function which will push the address of the next instruction to the stack (the return address) and then jump to the specified address. So after that, the stack should look like this so far:

+-----------------+
| Return Address  |
+-----------------+
| Function args   |
+-----------------+

Then at the sub-procedure, you save BP and you would actually “create a new stack” by having the bottom of the stack (BP – Base Pointer) point to the top of the stack:

New simulated empty stack
for current function
                    
+-----------------+ <--- BP = new stack frame base;         
| Saved BP Addr   |      SP = top of old stack frame
+-----------------+         = bottom of new stack frame;
| Return Address  |
+-----------------+
| Function args   |
+-----------------+

Everything below the base of the new stack frame are variables belonging to other functions, with the exception of the first 3 elements being the Saved BP, the return address, and the function arguments. These elements can be addressed by BP + the offset number of the element. Everything above BP in the new stack frame are the function’s local variables, these variables can be addressed by BP – the offset number of the element.

Here’s a simple example in C:

void main() {
char c;
c=0x69;
}

In assembly, that would translate to:

call main
mov ah,4ch         ;Index of exit function
int 21h            ;Execute exit function
main:
push bp            ;Save bottom of stack
mov bp,sp          ;Start new stack at the top
sub sp,0001        ;Allocate 1 byte (char) of space
mov [bp-0001],69h  ;c = 0x69
mov sp,bp          ;restore sp
pop bp             ;restore bp
ret                ;return from main()

Check out this example in C:

void useless(short i) {
char c;
c=0x24;
}

void main() {
short i;
i=0x1234;
useless(i);
}

Pretty useless code, in assembly (fasm) it translates to:

call main
mov ah,4ch                 ;Index of exit function
int 21h                    ;Execute exit function
main:
push bp                    ;Save bottom of current stack
mov bp,sp                  ;Create new stack at top
sub sp,0002                ;Allocate space for (short i)
mov word [bp-0002],1234h   ;i=0x1234
mov dx,word [bp-0002]      ;get value of i
push dx                    ;push argument
call useless               ;and call useless function
mov sp,bp                  ;restore old sp
pop bp                     ;restore old bp
ret                        ;end of main()
useless:
push bp                    
mov bp,sp                  
sub sp,0003                ;Allocate space for (short i) and (char c)
mov dx,word [bp+0004]      ;Get argument i (bp+0=saved bp, bp+2=return address)
mov word [bp-0002],dx      ;argument i becomes saved as local variable
mov word [bp-0003],0024h   ;char c=0x24
mov sp,bp
pop bp
ret

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: