Mechanisms in Procedures

Passing control

  • To beginning of procedure code
  • Back to return point

Passing data

  • Procedure arguments
  • Return value

Memory management

  • Allocate during procedure execution
  • Deallocate upon return

Others

  • Mechanisms all implemented with machine instructions
  • x86-64 implementation of a procedure uses only those mechanisms required

Stack Structure

x86-64 Stack

  • Region of memory managed with stack discipline
  • Grows toward lower addresses
  • Register %rsp contains lowest stack address(address of “top” element)

x86-64 Stack: Push

pushq Src: Fetch operand at Src, Decrement %rsp by 8, and write operand at address given by %rsp

x86-64 Stack: Pop

popq Dest: Read value at address given by %rsp, increment %rsp by 8, and store value at Dest(must be register)

Others

  • Deallocate not erase something, and just moving a stack pointer, the origin is still at the top of the ‘‘stack’’.

  • In most cases, Push and Pop can write as a set of instructions.

Calling Conventions

Procedure Control Flow

Use stack to support procedure call and return

Procedure call: call label

Push return address on stack, and jump to label

Return address

Address of the next instruction right after call

Procedure return: ret

Pop address from stack, and jump to address

Control Flow Example #1

Control Flow Example #2

Control Flow Example #3

Control Flow Example #4

Procedure Data Flow

In particular the rule is that the first six arguments get passed within 6 particular registers

  • First 6 arguments: %rdi, %rsi, %rdx, %rcx, %r8, %r9
  • Return value: %rax
  • stack: from up to down: Arg n, ..., Arg 8, Arg 7

The float point are passed in a separate set of registers.

Stack-Based Languages

Need some place to store state of each instantiation

  • Argument
  • Local variables
  • Return pointer

Stack Frames

Contents

  • Return information
  • Local storage (if needed)
  • Temporary space (if needed)

Management

  • Space allocated when enter procedure(“Set-up” code, Includes push by call instruction)
  • Deallocated when return(“Finish” code, Includes pop by ret instruction)

The base pointer which register %rbp indicates, but it is an optional pointer, if it not be used by base register, it will be used just as a regular register.

There’s a few special cases where it can’t know in advance how much space will be allocated, when it has to allocate an array or a memory buffer of variable size, and then it will actually use the %rbp in those cases for exactly that purpose.

if we have to pass more than six arguments, the caller will actually use its own stack frame to store those arguments.

if we’re making use of a base pointer, then we have to have some way to store the old value of the base pointer.

But in general if there’s some local state, Like some register that need to be saved, it will use the same way.

Example: Calling incr

1
2
3
4
5
long call_incr() {
long v1 = 15213;
long v2 = incr(&v1, 3000);
return v1 + v3;
}
1
2
3
4
5
6
call_incr:
subq $16, %rsp #locate
...
addq 8(%rsp), &rax #save result
addq $16, %rsp #deallocate
ret

The compiler can built into it figured out how much space it would need for this particular function, and it allocates that when it comes in, and it deallocates it when it goes out.

Register Saving Convertions

when procedure yoo calls who

1
2
3
4
5
6
7
yoo:
...
movq $15213, %rdx
call who
addq %rdx, %rax
...
ret
1
2
3
4
5
who:
...
subq $18213, %rdx
...
ret

Contents of register %rdx overwritten by who

Caller Saved

Caller saves temporary values in its frame before the call

Callee Saved

Callee saves temporary values in its frame before using

Callee restores them before returning to caller

Example

1
2
3
4
5
long call_incr2(long x) {
long v1 = 15213;
long v2 = incr(&v1, 3000);
return x + v2;
}
1
2
3
4
5
6
7
call_incr2:
pushq %rbx
subq $16, %rsp
...
addq $16, %rsp
popq %rbx
ret