In Pascal and other similar languages, a compiler must generate code so that each time a procedure is called during the execution of a program a stack frame is built for that procedure. Within that stack frame several important items are stored, each of which can generally be found at a fixed position within the frame. One of the things to be stored as a stack frame is being constructed is the return point of the procedure. In addition to the return point, space is allocated for the procedure's local variables and several other values that are both machine and language-dependent.
On return from a procedure, the corresponding stack frame must be removed from the stack. To keep track of the top position of the stack, almost all microprocessors include a stack pointer register. In addition, it is common, but not absolutely necessary, to have a separate pointer called the frame pointer, which points to the frame of the current stack. One of the additional items that is stored in each stack frame is the previous value of the frame pointer, so that
the frames are linked together in a list. For example, consider a procedure P in which, the local variables x1 and x2are declared. Furthermore, suppose that within P there is a procedure Q in which the local variables y1and y2 have been declared. The actual structure of the run time stack, as well as the actual layout of the stack frames for P and Q just after P has called Q, are shown in Fig. 3.12. We are assuming for this discussion that the stack builds down in memory. Although this is by far the most common approach, there are some processors that use the opposite convention and build up. In this picture, the return point for each procedure is the first item stored in each stack frame as the record is being constructed. It is either stored there automatically by the call instruction that is used to call Q, or, in the case where the call instruction puts the return point in the register, it is stored in the frame as one of the first actions of Q.
The second item that is pushed onto the stack is usually the previous value of the frame pointer, the frame pointer of the previous stack frame owned by the procedure that did the call. It is necessary to store this value so that when procedure Q returns to procedure P, the frame pointer can be restored so that it is once again pointing to the correct place. The remainder of the stack frame is used for the local variables.
While procedure Q is executing, the frame pointer will point to the location in the stack frame for Q used to store the old value of the frame pointer. Since we intend to allocate all local variables at fixed locations in this stack frame just below where the frame pointer points, we know that y1can be found at an offset of 4 from the frame pointer and y2 can be found at an offset of 8 (assuming that the old frame pointer as well as y1 and y2are 4-byte values). These days, stack-based languages, including C and Pascal, are in common use, and furthermore, they all support dynamic storage allocation. Modern CISC designs especially reflect anticipated use of more complicated addressing modes that arise from the use of a stack and dynamically allocated data.
Postfix notation. A stack processes data using postfix or inverse polish notation. Braces are absent in inverse polish notation, e.g., expression "(a + b) * (c - d) / sin(e)" is written as "a b + c d - * e sin /". Stack machines have been designed for direct executing of inverse polish notation. When analyzing a string, a variable is met it is pushed into the stack, and when a sign of mathematical operation is met, the necessary number of variables are popped from the stack, the operation is executed and the result is pushed into the stack. To the end of analyzing the string it is necessary only to pop the result from the stack.