<<

Machine Code: Procedures

Return %rax %eax %r8 %r8d Arg 5 %rbx %ebx %r9 %r9d Arg 6 Arg 4 %rcx %ecx %r10 %r10d Arg 3 %rdx %edx %r11 %r11d Arg 2 %rsi %esi %r12 %r12d Arg 1 %rdi %edi %r13 %r13d Stack ptr %rsp %esp %r14 %r14d %rbp %ebp %r15 %r15d

Sean Barker 1

Call Stack

Stack “Bottom”

Increasing Addresses

Stack Grows Down Stack Pointer: %rsp

Stack “Top”

Sean Barker 2 Stack Operations

Stack “Bo8om” Stack “Bo;om”

Increasing Increasing Addresses Addresses

Stack Grows Stack Down Grows Stack Pointer: %rsp Down -8 Stack Pointer: %rsp +8

Stack “Top” Stack “Top” pushq Src popq Dest 1. Decrement %rsp by 8 1. Read (%rsp) to Dest 2. Write Src to (%rsp) 2. Increment %rsp by 8

Sean Barker 3

Procedure Call Example

long x = add(3, 5); long add(long x, long y) { doSomething(x); return x + y; }

movq $3, %rdi movq $5, %rsi add: callq add movq %rdi, %rax movq %rax, %rdi addq %rsi, %rax callq doSomething ret

Sean Barker 4 Procedure Call Return Addresses (1)

• Stack 0x130 • Grows 0000000000400540 : Down • 0x128 • • 0x120 400544: callq 400550 400549: mov %rax,(%rbx) • • %rsp 0x120

%rip 0x400544 0000000000400550 : 400550: mov %rdi,%rax • • 400557: retq

Sean Barker 5

Procedure Call Return Addresses (2)

• Stack 0x130 • Grows 0000000000400540 : Down • 0x128 • • 0x120 400544: callq 400550 400549: mov %rax,(%rbx) 0x118 0x400549 • • %rsp 0x118

%rip 0x400550 0000000000400550 : 400550: mov %rdi,%rax • • 400557: retq

Sean Barker 6 Procedure Call Return Addresses (3)

• Stack 0x130 • Grows 0000000000400540 : Down • 0x128 • • 0x120 400544: callq 400550 400549: mov %rax,(%rbx) 0x118 0x400549 • • %rsp 0x118

%rip 0x400557 0000000000400550 : 400550: mov %rdi,%rax • • 400557: retq

Sean Barker 7

Procedure Call Return Addresses (4)

• Stack 0x130 • Grows 0000000000400540 : Down • 0x128 • • 0x120 400544: callq 400550 400549: mov %rax,(%rbx) • • %rsp 0x120

%rip 0x400549 0000000000400550 : 400550: mov %rdi,%rax • • 400557: retq

Sean Barker 8 Passing Data

Registers Stack ¢ First 6 arguments

%rdi • • •

%rsi Arg n %rdx Stack Grows %rcx • • • Down %r8 Arg 8 %r9 Arg 7 ¢ Return value Stack “Top” %rax

Sean Barker 9

Stack Frames

Older Previous Stack Frame Frames

Frame/Base Pointer: %rbp (Optional) x Frame for proc

Stack Pointer: %rsp

Stack “Top”

Sean Barker 10 Call Chain Example

foo(…) { • • bar(…) bar(); { • • • • • baz(); } baz(…) • • • { baz(); • • • • • } baz(); • • }

Procedure baz() is recursive

Sean Barker 11

Stack Frame Allocation (1)

Stack

foo foo(…) %rbp { foo • %rsp • bar(); • • }

call bar

Sean Barker 12 Stack Frame Allocation (2)

Stack

foo(…) foo { bar(…) •{ foo • • • bar • %rbp whobaz();(); • • • • bar %rsp • baz(); } • • • } call baz

Sean Barker 13

Stack Frame Allocation (3)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • • • • • baz bar • • amI(); baz(); %rbp } • • • } • baz • %rsp }

call baz (recurse)

Sean Barker 14 Stack Frame Allocation (4)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • baz(…) • • • • baz bar • { • amI(); baz();• } • • • • } • baz baz • baz(); } • %rbp • baz } %rsp call baz (recurse)

Sean Barker 15

Stack Frame Allocation (5)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • baz(…) • • • • baz bar • { • amI(); baz(…) baz();• } • • • • { • baz baz } baz();• • • } • • baz(); baz baz } • • } %rbp baz return %rsp (base case)

Sean Barker 16 Stack Frame Allocation (6)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • baz(…) • • • • baz bar • { • amI(); baz();• } • • • • } • baz baz • baz(); } • %rbp • baz baz } %rsp return (unwinding recursion)

Sean Barker 17

Stack Frame Allocation (7)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • • • • • baz bar • • amI(); baz(); %rbp } • • • } • baz baz • %rsp } baz return (unwinding recursion)

Sean Barker 18 Stack Frame Allocation (8)

Stack

foo(…) foo { bar(…) •{ yoofoo • • • bar • %rbp whobaz();(); • • • • baz bar • baz(); %rsp } • • • } baz call baz baz

Sean Barker 19

Stack Frame Allocation (9)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • • • • • baz baz bar • • amI(); baz(); %rbp } • • • } • baz baz • %rsp } baz return (base case)

Sean Barker 20 Stack Frame Allocation (10)

Stack

foo(…) foo { bar(…) •{ yoofoo • • • bar • %rbp whobaz();(); • • • • baz baz bar • baz(); %rsp } • • • } baz return baz

Sean Barker 21

Stack Frame Allocation (11)

Stack

foo foo(…) %rbp { yoofoo • bar %rsp • bar(); baz baz • • } baz return baz

Sean Barker 22 Caller vs. Callee (1)

Stack

foo(…) foo { bar(…) •{ foo Caller frame • • • bar • %rbp whobaz();(); • • • • bar Callee frame • baz(); %rsp } • • • } foo is the caller bar is the callee

Sean Barker 23

Caller vs. Callee (2)

Stack

foo(…) foo { bar(…) •{ yoofoo baz(…) bar • • • • { whoamI();(); • • • • • baz bar Caller frame • • amI(); baz(); %rbp } • • • } • baz Callee frame • %rsp } bar is the caller baz is the callee

Sean Barker 24 Stack Frame Components

Older Stack Frames Caller Frame Arguments 7+ Frame pointer Return Addr %rbp (optional) Saved Registers + Local Callee Variables Frame

Argument Stack pointer Build %rsp (optional)

Stack “Top”

Sean Barker 25

Using the Stack (1)

long incr(long* p, long val) { long x = *p; long y = x + val; *p = y; return x; }

incr: Register Use(s) movq (%rdi), %rax addq %rax, %rsi %rdi Argument p movq %rsi, (%rdi) %rsi Argument val, y ret %rax x, Return value

Sean Barker 26 Using the Stack (2)

Initial Stack Structure long foo() { long v1 = 15213; long v2 = incr(&v1, 3000); . . . caller frame return v1+v2; (e.g., main) } Rtn address %rsp

foo: subq $16, %rsp Resulting Stack Structure movq $15213, 8(%rsp) movl $3000, %esi leaq 8(%rsp), %rdi . . . caller frame call incr addq 8(%rsp), %rax (e.g., main) addq $16, %rsp Rtn address ret 15213 %rsp+8 callee frame Unused %rsp (foo)

Sean Barker 27

Using the Stack (3)

Stack Structure long foo() { long v1 = 15213; long v2 = incr(&v1, 3000); . . . caller frame return v1+v2; } (e.g., main) Rtn address 15213 %rsp+8 callee frame Unused %rsp (foo) foo: subq $16, %rsp movq $15213, 8(%rsp) Register Use(s) movl $3000, %esi %rdi &v1 leaq 8(%rsp), %rdi call incr %rsi 3000 addq 8(%rsp), %rax addq $16, %rsp ret

Sean Barker 28 Using the Stack (4)

Stack Structure (a

Sean Barker 29

Using the Stack (5)

Stack Structure

long foo() { long v1 = 15213; . . . caller frame long v2 = incr(&v1, 3000); (e.g., main) return v1+v2; Rtn address } 18213 %rsp+8 callee frame Unused %rsp (foo)

foo: subq $16, %rsp Register Use(s) movq $15213, 8(%rsp) %rax Return value movl $3000, %esi leaq 8(%rsp), %rdi Updated Stack Structure call incr addq 8(%rsp), %rax addq $16, %rsp . . . caller frame ret (e.g., main) Rtn address %rsp

Sean Barker 30 Using the Stack (6)

Updated Stack Structure long foo() { long v1 = 15213; long v2 = incr(&v1, 3000); . . . caller frame return v1+v2; } (e.g., main) Rtn address %rsp

foo: subq $16, %rsp Register Use(s) movq $15213, 8(%rsp) %rax Return value movl $3000, %esi leaq 8(%rsp), %rdi Final Stack Structure call incr addq 8(%rsp), %rax addq $16, %rsp . . . ret %rsp

Sean Barker 31

Stack Frame Components

Older Stack Frames Caller Frame Arguments 7+ Frame pointer Return Addr %rbp (optional) Saved Registers + Local Callee Variables Frame

Argument Stack pointer Build %rsp (optional)

Stack “Top”

Sean Barker 32 Register Conventions

Return value (caller-saved) %rax %rdi %rbx %rsi %r12

Arguments %rdx Callee-saved %r13 Temporaries (caller-saved) %rcx %r14 %r8 %r15 %rbp %r9 Special Caller-saved %r10 %rsp temporaries %r11

Sean Barker 33

Caller-Saved vs. Callee-Saved (1)

alice: movq X, %reg # compute X callq bob Could overwrite %reg! movq %reg, ... # use X

Caller-Saved %reg Callee-Saved %reg alice: alice: movq X, %reg # compute X pushq %reg # save caller's pushq %reg # save X movq X, %reg # compute X callq bob # might change X callq bob # preserves X popq %reg # restore X movq %reg, ... # use X movq %reg, ... # use X popq %reg # restore caller

Sean Barker 34 Caller-Saved vs. Callee-Saved (2)

alice: movq X, %reg # compute X callq bob ... # don't need X again

Caller-Saved %reg Callee-Saved %reg alice: alice: movq X, %reg # compute X pushq %reg # save caller's callq bob # might change X movq X, %reg # compute X ... callq bob # preserves X ... popq %reg # restore caller

Avoids save/restore!

Sean Barker 35

Caller-Saved vs. Callee-Saved (3)

alice: Caller-Saved %reg movq X, %reg # compute X alice: callq bob movq X, %reg # compute X movq %reg, ... # use X pushq %reg # save X callq charlie callq bob # might change X movq %reg, ... # use X popq %reg # restore X movq %reg, ... # use X Callee-Saved %reg pushq %reg # save X callq charlie # might change alice: popq %reg # restore X pushq %reg # save caller's movq %reg, ... # use X movq X, %reg # compute callq bob # preserves X movq %reg, ... # use X Only one save/restore! callq charlie # preserves X movq %reg, ... # use X popq %reg # restore caller

Sean Barker 36 Callee-Saved Example (1)

Initial Stack Structure long foo2(long x) { long v1 = 15213; long v2 = incr(&v1, 3000); . . . return x+v2; } Rtn address %rsp

foo2: pushq %rbx Resulting Stack Structure subq $16, %rsp movq %rdi, %rbx movq $15213, 8(%rsp) . . . movl $3000, %esi leaq 8(%rsp), %rdi call incr Rtn address addq %rbx, %rax Saved %rbx addq $16, %rsp 15213 %rsp+8 popq %rbx ret Unused %rsp

Sean Barker 37

Callee-Saved Example (2)

Resulting Stack Structure

long foo2(long x) { long v1 = 15213; . . . long v2 = incr(&v1, 3000); return x+v2; Rtn address } Saved %rbx 15213 %rsp+8 foo2: pushq %rbx Unused %rsp subq $16, %rsp movq %rdi, %rbx movq $15213, 8(%rsp) Pre-return Stack Structure movl $3000, %esi leaq 8(%rsp), %rdi call incr . . . addq %rbx, %rax addq $16, %rsp Rtn address %rsp popq %rbx ret

Sean Barker 38 Recursive Example

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Sean Barker 39

Recursive Base Case

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type %rdi x Argument . . .

%rax Return value Return value Rtn address %rsp

Sean Barker 40 Recursive Register Save

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type %rbx Caller's value Callee-saved . . .

Rtn address Caller's value! Saved %rbx %rsp

Sean Barker 41

Recursive Call Setup

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type %rbx x & 1 Callee-saved . . .

%rdi x >> 1 Recursive arg Rtn address Saved %rbx %rsp

Sean Barker 42 Recursive Call

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type %rbx x & 1 Callee-saved . . .

%rax Subcall result Return value Rtn address Saved %rbx %rsp

Sean Barker 43

Recursive Result

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type %rbx x & 1 Callee-saved . . .

%rax Combined result Return value Rtn address Saved %rbx %rsp

Sean Barker 44 Recursive Completion

bitcount_r: /* recursive bitcount */ movl $0, %eax long bitcount_r(unsigned long x) { testq %rdi, %rdi if (x == 0) { je .L6 return 0; pushq %rbx } else { movq %rdi, %rbx long bit = x & 1; andl $1, %ebx long rest = bitcount_r(x >> 1); shrq %rdi return bit + rest; call bitcount_r } addq %rbx, %rax } popq %rbx .L6: ret

Register Use(s) Type

%rax Combined result Return value . . .

Rtn address %rsp

Sean Barker 45

Stack Frame Components

Older Stack Frames Caller Frame Arguments 7+ Frame pointer Return Addr %rbp (optional) Saved Registers + Local Callee Variables Frame

Argument Stack pointer Build %rsp (optional)

Stack “Top”

Sean Barker 46