CMPT 295: Unit - Machine-Level Programming
Lecture 19:
- Assembly language
- Program Control
- Function Call and Stack
- Managing Local Data
Last lecture
- Passing data mechanism
- x86-64 function call convention:
First 6 arguments:
Name | Register |
---|---|
argument 1 | %rdi |
argument 2 | %rsi |
argument 3 | %rdx |
argument 4 | %rcx |
argument 5 | %r8 |
argument 6 | %r9 |
return value | %rax |
Stack:
Register | Stack | Note |
… | ||
argument n | Stored onto the stack in reverse order | |
… | Stored onto the stack in reverse order | |
argument 8 | Stored onto the stack in reverse order | |
%rsp | argument 7 | Stored onto the stack in reverse order |
Today’s Menu
- Introduction
- C program -> assembly code -> machine level code
- Assembly language basics: data, move operation
- Memory addressing modes
- Operation leaq and Arithmetic & logical operations
- Conditional Statement – Condition Code + cmovX
- Loops
- (highlighted) Function call – Stack
- Overview of Function Call
- Memory Layout and Stack - x86-64 instructions and registers
- Passing control
- Passing data – Calling Conventions
- (highlted) Managing local data
- Recursion
- Array
- Buffer Overflow
- Floating-point operations
To recap …
- Overview of Function Call mechanisms:
- What happens when a function (caller) calls another function (callee)?
- Control is passed … * To the beginning of the code in callee function * Back to where callee function was called in caller function
- Data is passed … (last lecture) * To callee function via function parameter(s) * Back to caller function via return value
- Memory is … (allocated a stack frame on the stack, but what can be stored on this stack frame?) * Allocated when callee function starts executing * Deallocated when callee function stops executing
- What happens when a function (caller) calls another function (callee)?
3. Managing local data
- When writing assembly programs, what can we use when we need space for our local data?
- We can use registers!
- Yes! Registers are our first choice as they are the fastest storage location on a computer.
- OK! but, since registers are shared by all functions in x86-64 assembly language, we need to follow some convention, otherwise … :
- We can use registers!
Assembly 1 (x86-64 function call convention):
who:
...
movq $15213, %rbx
call amI
addq %rbx, %rax
...
ret
Assembly 2:
amI:
...
subq $18213, %rbx
...
ret
Register Table:
Register | Value |
---|---|
%rbx |
3. Managing local data - “register saving” convention => callee saved registers
“register saving” conventions:
- calle saved registers
When we need space for our local data …
- Registers
- A function can utilise unused registers (only when needed)
- Some registers are referred to as callee saved registers:
%rbx
,%rbp
,%r12
to%r15
(and%ebx
,%bx
,%bl
, …) * Callee saved registers means that … * the callee function must preserve the values of these registers before using them, * then restore their values before the control is returned (through the execution of ret instruction) to the caller function
3. Managing local data - “register saving” convention => callee saved registers
- How can callee preserve the values of these callee saved registers before using them?
- Example of a scenario:
- Caller uses
%r13
- Caller calls callee
- At the start of callee, callee
pushq %r13
- Then callee uses %r13
- Then before execution flow returns from callee to caller (via ret), callee popq %r13 (Note: If callee pushq more than 1 register, then callee popq them in reverse order)
- The execution flow returns to caller which continues using %r13
- Caller uses
- Example of a scenario:
Callee saved registers:
Upon return from callee, caller can always assume that these registers still contain the values caller stored in them before calling callee!
3. Managing local data - “register saving” convention => caller saved registers
Register saving conventions:
- Callee saved registers
-
Caller saved registers
- Registers (cont’d)
- Some registers are referred to as caller saved registers:
- %r10, %r11, %rax and all 6 registers used for passing data as arguments to callee (and %r10d, %r10w, %r10b, …) * Caller saved registers means that … * the caller function must preserve the values of these registers before …
- setting up the callee‘s argument(s) into the appropriate “data passing as argument” register(s) and
- calling the callee * then once the control is returned to the caller, the caller must restore their values before using them.
Managing local data - “register saving” convention => caller saved registers
- How can caller preserve the values of these caller saved registers before using them?
- Example of a scenario:
- Caller uses %r10
- Before calling callee, caller pushq %r10 then calls callee
- Callee uses %r10
- Then after the execution flow has returned from callee to caller (via ret), caller popq %r10 (If caller pushq more than 1 register, then caller popq them in reverse order)
- Caller continues using %r10
- Example of a scenario:
caller saved registers:
Callee can always assume that caller has saved the content of these registers, so it is “safe” for callee to use them!
x86-64 “register saving” convention
Solution 1:
who:
...
movq $15213, %rbx
call amI
addq %rbx, %rax
...
ret
amI:
subq $18213, %rbx
ret
Solution 2:
who:
...
movq $15213, %r10
call amI
addq %r10, %rax
...
ret
amI:
...
subq $18213, %r10
...
ret
base + displacement | Stack Variable | Purpose |
---|---|---|
Register Table:
Register | Value |
---|---|
3. Managing local data => spilling
- When writing assembly programs, what can we use when we need space for our local data?
- We can use stack! (If we run out of registers).
-
2) Stack
- A function can use the stack to store the values of its local variables and for temporary spaceMust remember to clean-up the stack before returning to caller!
- Set-up and Clean-up code:
- Example:
subq $16, %rsp
andaddq $16, %rsp
- Example:
- To spill onto the stack:
- Example: movq %rax, 56(%rsp)
Must remember to clean-up the stack before returning to caller.
Local variables on Stack – Example
long incr(long *p, long val)
{
long x = *p;
long y = x + val;
*p = y;
return x;
}
long call_incr() {
long v1 = 15213;
long v2 = incr(&v1, 3000);
return v1+v2;
}
Assembly:
call_incr:
subq $16, %rsp # highlighted
movq $15213, 8(%rsp) # highlighted
movl $3000, %esi
leaq 8(%rsp), %rdi
call incr
addq 8(%rsp), %rax
addq $16, %rsp
ret
Register | M[] Stack |
%rsp |
base + displacement | Stack Variable | Purpose |
---|---|---|
Register Table:
Register | Value |
---|---|
Summary - x86-64 “register saving” convention
callee saved registers:
- Callee must save & restore before modifying
Register | Value | Note |
---|---|---|
%rbx | ||
%r12 | ||
%r13 | ||
%r14 | ||
%r15 | ||
%rbp | Parameters/arguments | |
%rsp | return value |
caller saved registers:
- Caller must save & restore
- Can be modified by callee
Register | Value | Note |
---|---|---|
%rax | Return value | |
%rax | Parameters/arguments | |
%rdi | Parameters/arguments | |
%rsi | Parameters/arguments | |
%rdx | Parameters/arguments | |
%rcx | Parameters/arguments | |
%r8 | Parameters/arguments | |
%r9 | Parameters/arguments | |
%r10 | ||
%r11 |
Summary - x86-64 conventions and stack frame
- caller preserves caller saved registers (arrow)
- caller passes arguments (arrow)
- caller calls callee (arrow)
- callee preserves callee saved registers (arrow)
- callee constructs local vars (get stack space) (arrow)
- callee performs function
- callee recycles local vars (restore stack space)
- callee restores callee saved registers
- callee returns to caller
- caller pops arguments
- caller restores caller saved registers
M[] Stack | Note |
---|---|
… | caller frame |
caller saved regs | caller frame |
args 7 … n | caller frame |
return address | caller frame |
callee saved regs | callee frame |
%rsp/Top/local vars | callee frame |
Next lecture
- Introduction
- C program -> assembly code -> machine level code
- Assembly language basics: data, move operation
- Memory addressing modes
- Operation leaq and Arithmetic & logical operations
- Conditional Statement – Condition Code + cmovX
- Loops
- (highlighted) Function call – Stack
- Overview of Function Call
- Memory Layout and Stack - x86-64 instructions and registers
- Passing control
- Passing data – Calling Conventions
- Managing local data
- (highlighted) Recursion
- (highlighted) Array
- Buffer Overflow
- Floating-point operations