Procedure
- Suppose procedure P calls procedure Q, and Q then executes and returns back to P.
Run-time Stack
- C programs use the (run-time) stack for local variables, function parameters, and return addresses.

- When procedure P calls procedure Q, it’ll push the return address onto the stack, indicating where within P the program should resume execution once Q returns
Control transfer
| Instruction | Description |
|---|---|
| call Label | Procedure call |
| call *Operand | Procedure call |
| ret | Return from call |
-
The instruction
callQ pushes an address A onto the stack, sets the PC to the beginning of Q. -
The pushed address A is referred as the
return addressand is computed as the address of the instruction immediately following the call instruction. -
The counterpart instruction
retpops an address A off the stack and sets the PC to A. -
Example: consider the following C code
long mult2(long, long);
void multstore(long x, long y, long *dest) { long t = mult2(x, y); *dest = t;}

-
In this code, we can see that:
- The
callqinstruction with address0x400563inmaincalls functionmultstore. - The effect of
callis to pushes the next instruction address (0x400568) to top of the stack - Then jumps to the instruction in function
multstoreat address0x400540(by set this value to %rip register). - The execution of
multstorecontinues until it hits theretqinstruction at0x40054d. - The instruction
retqpops0x400568from the stack and jumps to this address (by set this value to %rip register), resuming the execution ofmain
- The
-
Example:

Data transfer
-
In addition to passing control to a procedure when called, and then back again when the procedure returns, procedure calls may involve passing data as arguments, and returning from a procedure may also involve returning a value.
-
With x86_64, up to 6 integral (integer and pointer) arguments can be passed via registers.

-
When a function has more than 6 integral arguments, the other ones are passed on the stack.
Local Storage on the Stack (stores local variable)
-
Not enough registers to hold all of the local data.
-
The address operator
&is applied to local variable, and hence we must be able to generate an address for it. -
Some of the local variables are arrays or structures and hence must be accessed by array or structure references.
-
Portion of the stack frame labeled “Local variables”
-
Consider this example:

-
Example 2:

Local storage in registers (stores local variable)
-
Callee-saved registers: %rbx, %rbp, %r12-%r15
-
When procedure P calls procedure Q, Q must preserve the values of these registers, ensuring that they have the same values when Q returns to P as they did when Q was called. Procedure Q can preserve a register value by either not changing it at all or by pushing the original value on the stack, altering it, and then popping the old value from the stack before returning. The pushing of register values has the effect of creating the portion of the stack frame labeled “Saved registers” in Figure 3.25. With this convention, the code for P can safely store a value in a callee-saved register (after saving the previous value on the stack, of course), call Q, and then use the value in the register without risk of it having been corrupted.
-
Consider the following example:

- Initially,
xis in %rdi,yis in %rsi, if we want to callQ(y), somehow we must pass the value ofyinto the%rdiregister (1st arg), but before that we need to save the value x somewhere (%rbp in this case). Same goes forx. - Function
Pwill use%rbpand%rbxregisters to save x, y. Since they’recallee-saved, functionPwill have to pushing them to the stack (Saved registersportion). - At the end of the function, it restores the values from the stack into these 2 registers.
- Initially,
Recursive procedures
Variable-size stack frames
-
Consider an example of a function containing a variable-size array.

-
The function declares local array
pofnpointers, wherenis given by the first argument. This requires allocation8nbytes on the stack, where the value ofnmay vary from one call of the function to another. -
The compiler therefore can’t determine how much space it must allocate for the function’s stack frame.
-
In addition, the program generates a reference to the address of the local variable
i(so this variable must be stored on the stack). -
During execution, the program must be able to access both local variable i and the elements of array p. On returning, the function must deallocate the stack frame and set the stack pointer to the position of the stored return address.
-
To manage a variable-size frame, x86_64 code usees register
%rbpto serve as a frame pointer (or base pointer). When using a frame pointer, the stack frame is organized as shown below:
- The code starts by pushing the current value of %rbp onto the stack and setting %rbp to point to this stack position (lines 2–3).
- Next, it allocates 16 bytes on the stack, the first 8 of which are used to store local variable i, and the second 8 of which are unused.
- Then it allocates space for array p (lines 5–11).