7 Machine Level Programming III Procedures
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 | long call_incr() { |
1 | call_incr: |
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 | yoo: |
1 | who: |
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 | long call_incr2(long x) { |
1 | call_incr2: |