A portion of a computer's stack set up to handle a function call. This is where the variables the function uses to operate, the saved registers a function uses, the return address of the calling function, and the base pointer are located. It's an essential part of learning how to program functions in assembly language.

A typical stack frame

The easiest way to understand this is to show a typical stack frame
           | Top of Stack   |
           ------------------
           |                |
           |   Calling      |
           |   Parameters   |
           |                |
           ------------------
           | Return Address |
           ------------------
           | Saved Base Ptr.|    
           ------------------    <--- Base Pointer points to 
           |                |            this memory location
           | Local          |
           |      Variables |
           ------------------
           | Saved          |
           |      Registers |
           ------------------
           |  Rest of Stack |


An Explanation of these terms:

  • Calling Parameters - These are the variables you're passing to the program to work on. In languages such as C, and Java, these are the portions inside the parentheses in your function call.
  • Return Address - The location in the program you come back to after your function completes. If this gets screwed up, Bad Things can happen
  • Saved Base Pointer - The old value of the base pointer. Important because your function could be called by other functions, and you want to make sure their stack frame is correct
  • Base Pointer - A register set aside primarily for dealing with functions and stack frames. The Base Pointer provides a fixed reference for dealing with items located on the stack. This provides a baseline to refer to variables given to the function by the calling routine, plus variables local to the function itself.
  • Local Variables - Unlike variables used in the main program, which are allocated at compile-time, variables used in local functions are allocated at execution time by taking space off the stack.
  • Saved Registers - It's very important that one saves the registers they use in the function. Your function will be called by other programs which may need the content in those registers later on. If destroying a register cannot be avoided, notate it in your function's documentation so that people using the function can save the register for later use. Good programming practice, however, maintains that the only good reason for changing register values is to return values to the calling function.

A stack frame is set up by first pushing the values the function needs onto the stack. The function call instruction is then run, which pushes the memory address to return to onto the stack, and passes control to the called function. At this point, what occurs is up to the called function. If the function is well behaved, and done in accordance with any sort of programming styles, the base pointer is saved to the stack, the stack pointer is decremented by the size of all temporary variables used by the function, and all the registers used by the function are pushed onto the stack. At this point, the function is ready to be run.

Cleaning up the stack frame is the opposite of setting it up. The saved registers are popped off the stack, and the stack pointer is set to the value of the base pointer. The original value of the base pointer is then restored by popping it off the stack, and the return function call is then executed.

Depending on the program style, the way the return function call operates differs. If the program is done with pascal style functions, the function itself completely cleans the stack by removing the parameters of the function, usually by calling the return operation with the size of the parameters. If the program is written with C style functions, the calling function is placed in charge of cleaning up the parameters used in the function call. At this point, program control returns to the calling function.

Code Example

The following example code is written using Intel-style assembly notation, which is as follows: operation operand, operator. Comments are prefixed with a semicolon, and are affected until the next carriage return.

; example calling function

	...		;For the sake of this w/u,
			;we'll assume you know how to set up a
			;program
	push yadda	;Put the variable yadda onto the stack.
			;Yadda is the size of one word

	push emback	;Put the variable emback onto the stack. 
			;Emback is also the size of one word

	call example	;Call our example function

	...		;Run the rest of the program

;example function

example	PROC		;This section is the example function 
	push bp		;Save the old Base Pointer
	mov bp,sp	;Move the value of the stack into the
			;base pointer register

	sub sp, n	;Subtract n bytes from the stack
			;pointer, for use by the function for 
			;local variables.
			;n must be a multiple of the word
			;size on your system

	push ax		;Save our registers
	push bx
	push cx

	...		;Do whatever the program's gotta do

	pop cx		;Restore our registers in the reverse 
	pop bx		;order we saved them
	pop ax

	mov sp, bp	;Free up the stack space used by the
			;temporary variables

	pop bp		;Restore the base pointer

	return 4	;Return to the calling program, pascal
			;style.  Both variables pushed onto the
			;stack were words, which take up 2
			;bytes each.  We're telling the return 
			;operation to clear the four bytes of
			;the stack above the address of the
			;function call.  If there were 3 items
			;pushed onto the stack, the number would
			;be 6, if there were "n" items, the
			;number would be 2n.  If this were a C
			;style function, there would be no
			;number here.

example ENDP		;That's all for this function

Stack frames are an essential part of assembly language programming, and essentially, all programming. Every language, be it C, Pascal, Fortran, Ada, all use stack frames internally in order to set up their functions. It provides an easy and safe way to transfer flow to another routine in order to make programming easier. Stack frames are troublesome at first, but they truly aren't as bad as some of the other areas of assembly programming.