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
%rip 0x400544 0000000000400550
Sean Barker 5
Procedure Call Return Addresses (2)
• Stack 0x130 • Grows 0000000000400540
%rip 0x400550 0000000000400550
Sean Barker 6 Procedure Call Return Addresses (3)
• Stack 0x130 • Grows 0000000000400540
%rip 0x400557 0000000000400550
Sean Barker 7
Procedure Call Return Addresses (4)
• Stack 0x130 • Grows 0000000000400540
%rip 0x400549 0000000000400550
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