UMBC CMSC 211 Fall 1999 |
The bp (base pointer register points to a fixed location in the middle of the stack from of the currently executing procedure and the stack pointer sp points to the end of the procedure's temporary storage.
Because bp is an index register, the parts of the stack frame can be referenced relative to its contents by adding or subtracting a displacement. (Displacements are always referencing words!) These displacements are going to be the same for each and every use of a particular procedure. That way we we are use age as the third parameter, it will always be [bp + 6]. Additional, the si and di registers can be used.
Another rule is that the bp register always is used with the stack segment (ss) register, ss:bp. Do not modify the ss register, or you will mess up many things!!!!
The calling procedure must push the parameters on the stack before making the procedure call. Then the called procedure must save and reset the bp, reserve space for thelocal variables, save the appropriate registers, and do its work. Then it must restore things in reverse order:
Callee | PROC | ; Start of procedure | |
push | bp | ||
mov | bp, sp | ||
sub | sp, n | ; reserve n bytes of local storage | |
push | reg1 | ; save registers | |
push | reg2 | ||
; do some processing | |||
pop | reg2 | ||
pop | reg1 | ||
add | sp, n | ; just the opposite | |
mov | sp, bp | ||
pop | bp | ||
ret | ; we are done. |
This results in memory that looks like this:
When working with C functions, some of them have a variable number of parameters,
where each time the function can have a different (variable)
number of arguments. Printf is an example of this. It looks like:
There are two kinds of parameters, call by value and call by reference. We have been using call by value when we do the push. Since the values are not retained, whatever changes that are made to them are lost. Notice that this is the default for C for everything except for arrays. Since the size of anything being pushed is in units of 16 bits, when the parameter is a character, it is promoted to 16-bits.
Both recusion and reentrancy are also solved with this method, because every call means that a separate frame are being manipulated. Each call becomes independent!
The author points out that it is a poor design to have every procedure do its own I/O. Procedures should be small, simple, and only do one thing. Then libraries can be built up and only the current outer driver has to worry about whether to use the keyboard, CRT, modem, disk file, etc. The inner procedures are independent of the I/O constraints that change with most programs.