0% found this document useful (0 votes)
21 views43 pages

Slides 12 x86 Procedures

Uploaded by

Vishal Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views43 pages

Slides 12 x86 Procedures

Uploaded by

Vishal Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

x86

PROCEDURES
(FUNCTIONS)
CONTROL FLOW

Recall: Two ways to change program control flow


▸ “Jump” instructions
▸ “Call” instructions

Function
▸ A unit of code we can call
▸ Similar to a jump, except it can return
▸ Must support passing data as function arguments and return values

Also referred to as a procedure, method, or subroutine

But before we continue, we first have to understand how a stack works…

2
x86-64 STACK

Region of memory managed with last-in, first-out discipline


▸ Grows toward lower addresses
▸ %rsp Register indicates top element of stack
▹ “Top” element has lowest address

The stack is essential for function calls!

3
PUSHING TO A STACK

Pushing
▸ pushq Src
▹ Fetch operand at Src
▹ Decrement %rsp by 8
▹ Write operand at address given by %rsp

▸ e.g. pushq %rax


▹ subq $8, %rsp
▹ movq %rax,(%rsp)

4
POPPING FROM A STACK

Popping
▸ popq Dest
▹ Read operand at address given by %rsp
▹ Write to Dest
▹ Increment %rsp by 8

▸ e.g. popq %rax


▹ movq (%rsp),%rax
▹ addq $8,%rsp

5
STACK OPERATION EXAMPLES

6
CONTROL FLOW TERMINOLOGY

When foo calls who:


▸ foo is the caller, who is the callee
▸ Control is transferred to the ‘callee’

When function returns


▸ Control is transferred back to the ‘caller’

Last-called, first-return (LIFO) order


naturally implemented via stack

7
CONTROL FLOW INSTRUCTIONS

The hardware provides machine instructions for this:

Function call
▸ call label
▹ Push return address on stack
(that is, the address of next instruction after the call)
▹ Jump to label

Function return
▸ ret
▹ Pop return address from stack
▹ Jump to address

8
CONTROL FLOW EXAMPLE

9
CONTROL FLOW EXAMPLE

10
CONTROL FLOW EXAMPLE

11
CONTROL FLOW EXAMPLE

12
PRACTICE PROBLEM

What does this code do?

call next
next: The “call” will cause the address of the
popq %rax “popq” instruction to be pushed onto the
stack.

What is the value of %rax? Then, the popq instruction will pop that
address (its own address) off, and store
What would this be useful for?
it into rax.

Malware writers like to do this, because


it lets them figure out where in the
(virtual memory space) they are.
13
FUNCTION CALLS AND STACK FRAMES

For languages supporting recursion (C, Java), code must be re-entrant


▸ Multiple simultaneous instantiations of a single function
▸ Must store multiple versions of arguments, local variables, return address
▹ Return address
▹ Local variables
▹ Function arguments (if necessary)
▹ Saved register state (if necessary)

Implemented with stack frames


▸ Upon function invocation
▹ Stack frame created
▹ Stack frame pushed onto stack
▸ Upon function completion
▹ Stack frame popped off stack
▹ Caller’s frame recovered
14
CALL CHAIN EXAMPLE

15
CALL CHAIN EXAMPLE

16
CALL CHAIN EXAMPLE

17
CALL CHAIN EXAMPLE

18
CALL CHAIN EXAMPLE

19
CALL CHAIN EXAMPLE

20
CALL CHAIN EXAMPLE

21
CALL CHAIN EXAMPLE

22
CALL CHAIN EXAMPLE

23
CALL CHAIN EXAMPLE

24
CALL CHAIN EXAMPLE

25
CALL CHAIN EXAMPLE

26
CALL CHAIN EXAMPLE

27
X86-64 / LINUX STACK FRAME

Caller Stack Frame (Pink)


▸ Function arguments for callee
▹ Only used with 7+ integer arguments
▹ Arguments 1-6 passed in registers
▸ Return address
▹ Pushed by call instruction

Callee Stack Frame (Yellow) (From Top to Bottom)


▸ Old frame pointer (optional)
▸ Local variables (optional)
▹ If can’t keep in registers
▸ Saved register context (optional)
▹ If certain registers needed
▸ Function arguments for next call

28
X86-64 / LINUX STACK FRAME

Compiler can decide to simplify implementation


▸ Can omit local variables and saved registers for simple functions with few
variables
▸ Can avoid using pushq and popq to manage frame
▸ Can even avoid using the call instruction!

29
FUNCTION ARGUMENTS

Initially Passed via Registers Overflow onto stack when needed

%rdi
%rsi
%rdx Argument n
%rcx . . .
%r8 Argument 8
%r9 Argument 7

“Diane’s Silk Dress Cost 89 Dollars”

Return values given back on %rax


30
SWAP REVISITED

void swap(long *xp, long *yp) swap:


{ movq (%rdi), %rdx
long t0 = *xp; movq (%rsi), %rax
long t1 = *yp; movq %rax, (%rdi)
*xp = t1; movq %rdx, (%rsi)
*yp = t0; ret
}

Function arguments all passed in registers


▸ First argument (xp) in %rdi, second argument (yp) in %rsi
▸ 64-bit pointers

No stack operations required (except ret)


▸ Can hold all function arguments and local variables in registers
▸ Does not call another function so frame allocation not necessary 31
FUNCTION ARGUMENTS BEYOND 6
call_foo() {
long a[16];
foo(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
}

Given the C function above, identify function arguments being passed to foo:
0000000000000000 <call_foo>:
0: sub $0xA8,%rsp
7: mov 0x68(%rsp),%rax
a[9]
c: mov %rax,0x18(%rsp)
11: mov 0x60(%rsp),%rax
16: mov %rax,0x10(%rsp) a[8]
1b: mov 0x58(%rsp),%rax
20: mov %rax,0x8(%rsp) a[7]
25: mov 0x50(%rsp),%rax
2a: mov %rax,(%rsp) a[6]
2e: mov 0x48(%rsp),%r9 a[5]
33: mov 0x40(%rsp),%r8 a[4]
38: mov 0x38(%rsp),%rcx a[3]
3d: mov 0x30(%rsp),%rdx a[2]
42: mov 0x28(%rsp),%rsi a[1]
47: mov 0x20(%rsp),%rdi a[0]
4c: callq <foo>
51: add $0xA8,%rsp
58: retq 32
LOCAL VARIABLES

Held in registers if possible


▸ Allocate space on stack if too many (register spilling)
▸ Compiler allocates space on stack and updates %rsp

How are they preserved if the current function calls another function?
▸ Compiler updates %rsp beyond local variables before issuing “call”

What happens to them when the current function returns?


▸ Are lost (i.e. no longer valid)

33
LOCAL VARIABLES
call_foo() {
long a[16];
foo(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
}

0000000000000000 <call_foo>:
0: sub $0xA8,%rsp Makes room for both a[16] and partial
7: mov 0x68(%rsp),%rax argument build for foo.
c: mov %rax,0x18(%rsp)
11: mov 0x60(%rsp),%rax
16: mov %rax,0x10(%rsp)
1b: mov 0x58(%rsp),%rax
20: mov %rax,0x8(%rsp)
25: mov 0x50(%rsp),%rax
2a: mov %rax,(%rsp)
2e: mov 0x48(%rsp),%r9
33: mov 0x40(%rsp),%r8
38: mov 0x38(%rsp),%rcx
3d: mov 0x30(%rsp),%rdx
42: mov 0x28(%rsp),%rsi
47: mov 0x20(%rsp),%rdi
4c: callq <foo>
Puts the stack pointer back to where
51: add $0xA8,%rsp
it was at address 0x0.
58: retq 34
REGISTER SAVING CONVENTIONS

When function1() calls function2():


▸ function1 is the “caller”
▸ function2 is the “callee”

Can Register be Used for Temporary Storage?


▸ Need some coordination between caller and callee on register usage

Conventions
▸ “Caller Save”
▹ Caller saves temporary in its frame before calling
▸ “Callee Save”
▹ Callee saves temporary in its frame before using
▹ Callee restores values before returning

42
X86-64 CALLER SAVED REGISTERS

Can be modified by function being called

▸ %rax
▹ Return value

▸ %rdi, %rsi, %rdx, %rcx, %r8, %r9


▹ Function arguments

▸ %r10, %r11
▹ Temporaries

The caller is responsible for saving


these before a call!

43
X86-64 CALLEE SAVED REGISTERS

Function being called must save and restore

▸ %rbx, %r12, %r13, %r14, %r15

▸ %rbp
▹ May be used as frame pointer

▸ %rsp
▹ Special form of callee save
▹ Restored to original value upon
return from function

The callee (function being called) must


save/restore these registers if they want to use them.
44
X86-64 INTEGER REGISTERS

45
CALLEE SAVED EXAMPLE

46
CALLEE SAVED EXAMPLE

47
X86-64 FLOATING POINT ARGUMENTS

Recall integer arguments


▸ 64-bit registers used to pass
▸ %rdi, %rsi, %rdx, %rcx, %r8, %r9

Floating point
▸ Special vectored registers to pass (AVX-512)
▸ %zmm0 - %zmm31
▹ Capacity for a vector of 8 doubles
▹ Also used for vectored integer operations (more later)
▹ Unique to x64
▹ Special instruction sets: MMX -> SSE -> AVX -> AVX-512

48
32-BIT CALLING CONVENTIONS

Linux IA32 cdecl


▸ Caller pushes arguments on stack before call
▸ Caller clears arguments off stack after call

Win32 stdcall
▸ Caller pushes arguments on stack before call
▸ Callee clears arguments off stack before returning from call
▸ Saves some instructions since callee is already restoring the stack at the end of the
function

Fastcall
▸ Save memory operations by passing arguments in registers
▸ Microsoft implementation
▹ First two arguments passed in registers %ecx and %edx
▹ Code written on Windows must deal with stdcall and fastcall conventions
▸ Linux
▹ Must declare in function prototype which calling convention is being used
▹ http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
49
32-BIT CALLING CONVENTIONS

thiscall
▸ Used for C++

▸ Linux
▹ Same as cdecl, but first argument assumed to be “this” pointer

▸ Windows/Visual C++
▹ “this” pointer passed in %ecx
▹ Callee cleans the stack when arguments are not variable length
▹ Caller cleans the stack when arguments are variable length

50

You might also like