<<

CS 240251 SpringFall 2019 2020 FoundationsPrinciples of Programming of Computer Languages Systems λ Ben Wood Procedures and the The call stack discipline procedure call and return instructions x86 register-saving conventions

https://cs.wellesley.edu/~cs240/s20/ x86 Procedures 1 Why procedures? Why functions? Why methods? int contains_char(char* haystack, char needle) { while (*haystack != '\0') { if (*haystack == needle) return 1; haystack++; } return 0; }

Procedural Abstraction

x86 Procedures 2 Implementing procedures

1. How does a caller pass arguments to a procedure? ✓

2. How does a caller receive a return value from a procedure? ✓

3. Where does a procedure store local variables? ✓?

4. How does a procedure know where to return ?? (what code to execute next when done)?

5. How do procedures share limited registers and memory? ??

x86 Procedures 3 Call Chain Procedure call/return: Jump? yoo

yoo(…) { who • • • who(); • • • }

who(…) { yoo: • • • 1 2 who: • • • jmp who back: 5 3 • • • } 4

ru(…) { jmp back • • • }

But what if we want to call a function from multiple places in the code?

x86 Procedures 4 Call Chain Procedure call/return: Jump? Broken! yoo

yoo(…) { who • • • who(); ru ru • • • }

who(…) { who: • • • 1 ru(); 2 ru: • • • jmp ru back2: 6 ru(); 5 3,7 • • • } jmp ru 4 back2: ru(…) { 9 jmp back2 • • • 8 }

But what if we want to call a function from multiple places in the code?

Broken: needs to track context. x86 Procedures 5 Implementing procedures requires separate storage per call! (not just per procedure) 1. How does a caller pass arguments to a procedure? ✓

2. How does a caller receive a return value from a procedure? ✓

3. Where does a procedure store local variables? ✓?

4. How does a procedure know where to return ?? (what code to execute next when done)?

5. How do procedures share limited registers and memory? ??

x86 Procedures 6 Memory Layout reminder

Addr Perm Contents Managed by Initialized

N 2 -1 Stack RW Procedure context Run-time

Programmer, Dynamic RW malloc/free, Run-time Heap data structures new/GC Global variables/ Compiler/ RW Startup Statics static data structures Assembler/ Compiler/ R String literals Startup Literals Assembler/Linker Compiler/ X Instructions Startup Text Assembler/Linker

0 x86 Procedures 7 Call stack tracks context Example Call Chain yoo(…) yoo { • who • who(); • amI amI who(…) • { } • amI amI(); • amI(…) amI(); amI { • • } if(…){ amI() } • Procedure amI is recursive } (calls itself) x86 Procedures 8 Call stack tracks context Stack yoo(…) yoo { • yooyoo who • %rsp who(); • amI amI • } amI

amI

x86 Procedures 9 Call stack tracks context Stack yoo(…) yoo { who(…) •{ yooyoo who • • • • who();amI(); • • • • amI amI who • amI(); %rsp } • • • } amI

amI

x86 Procedures 10 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ • • who();amI();• • • •if( • …){ amI amI who • amI();amI() } • •} • } • amI amI } %rsp amI

x86 Procedures 11 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ •amI • (…) who();amI{();• • • •if( • …•){ amI amI who • amI();amIif(()…){ } • •} • amI() } •} amI amI } • } amI amI %rsp

x86 Procedures 12 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ •amI • (…) who();amI{();•amI(…) • • •if( •{…•){ amI amI who • amI();amIif(()…•){ } • •} • amIif(()…){ } •} amI() amI amI } •} } • amI } amI

amI %rsp

x86 Procedures 13 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ •amI • (…) who();amI{();•amI(…) • • •if( •{…•){ amI amI who • amI();amIif(()…•){ } • •} • amIif(()…){ } •} amI() amI amI } •} } • amI } amI

amI %rsp

x86 Procedures 14 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ •amI • (…) who();amI{();• • • •if( • …•){ amI amI who • amI();amIif(()…){ } • •} • amI() } •} amI amI } • } amI amI %rsp

amI

x86 Procedures 15 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • •{ • • who();amI();• • • •if( • …){ amI amI who • amI();amI() } • •} • } • amI amI } %rsp amI amI

amI

x86 Procedures 16 Call stack tracks context Stack yoo(…) yoo { who(…) •{ yoo yoo who • • who();amI(); • • amI amI who • amI(); %rsp } • } amI amI

amI amI

amI

x86 Procedures 17 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • {• who();amI();• • • if(){ amI amI who • amI();amI() } • } } • amI amI } %rsp amI

x86 Procedures 18 Call stack tracks context Stack yoo(…) yoo { who(…) •{ amI(…) yooyoo who • {• who();amI();• • • if(){ amI amI who • amI();amI() } • } } • amI amI } %rsp amI

x86 Procedures 19 Call stack tracks context Stack yoo(…) yoo { who(…) •{ yooyoo who • • who();amI(); • • amI amI who • amI(); %rsp } • } amI amI

amI

x86 Procedures 20 Call stack tracks context Stack yoo(…) yoo { • yooyoo who • %rsp who(); • amI amI who • } amI amI

amI

x86 Procedures 21 The call stack supports procedures. . . .

Stack frame: section of stack Saved Registers used by one procedure call to store context while running. Caller Local Variables Frame higher Extra Arguments addresses Procedure code manages to callee stack frames explicitly. Return Address • Setup: allocate space where to continue on return at start of procedure. • Cleanup: deallocate space stack grows before return. Callee Saved Registers toward Frame lower addresses Local Variables

Stack pointer . . . %rsp x86 Procedures 22 Procedure control flow instructions Procedure call: callq target 1. Push return address on stack 2. Jump to target

Return address: Address of instruction after call. 400544: callq 400550 400549: movq %rax,(%rbx)

Procedure return: retq 1. Pop return address from stack 2. Jump to return address

x86 Procedures 23 Call example Before callq Memory 0x7fdf30 • 0000000000400540 : • 0x7fdf28 • • 0x7fdf20 • 400544: callq 400550 0x7fdf18 ??? 400549: mov %rax,(%rbx) • %rsp %rip 0000000000400550• : 0x7fdf20 0x400544 400550: mov %rdi,%rax • • After callq Memory 400557: retq 0x7fdf30 • 0x7fdf28 • callq target 0x7fdf20 • 1. Push return address on stack 0x7fdf18 0x400549 2. Jump to target %rsp %rip 0x7fdf18 0x400550 x86 Procedures 24 Return example Before retq Memory 0x7fdf30 • 0000000000400540 : • 0x7fdf28 • • 0x7fdf20 • 400544: callq 400550 0x7fdf18 0x400549 400549: mov %rax,(%rbx) • %rsp %rip 0000000000400550• : 0x7fdf18 0x400557 400550: mov %rdi,%rax • • After retq Memory 400557: retq 0x7fdf30 • 0x7fdf28 • retq 0x7fdf20 • 1. Pop return address from stack 0x7fdf18 0x400549 2. Jump to return address %rsp %rip 0x7fdf20 0x400549 x86 Procedures 26 Procedure data flow conventions

First 6 arguments: Remaining arguments: passed in registers passed on stack (in memory) Arg 1 %rdi High Diane’s • • • Addresses Arg 2 %rsi Silk Dress Arg n Arg 3 %rdx Costs Arg 4 %rcx $8 9 • • • Arg 5 %r8 Arg 8 Arg 6 %r9 Arg 7 Low Return Address Addresses

Return value: Allocate stack space for arguments passed in %rax only when needed. %rax

x86 Procedures 27 callq puzzle optional

callq next next: popq %rax

What gets stored into %rax?

Why is there no ret instruction corresponding to the call?

What does this code do? (Hint: unusual use of call.)

x86 Procedures 28 Procedure data flow puzzle ex function body: huh( , , , ) { *p = d; return x - c; } Translated to x86 assembly: huh: Reverse engineer the x86 huh procedure movsbl %dl, %edx and the body of the C huh function to fill huh movl %edx, (%rsi) blanks in the C function header with: • the parameter types / order; and movswl %di, %edi • the return type. subl %edi, %ecx movl %ecx, %eax retq movsbl = move sign-extending a byte to a long (4-byte) movswl = move sign-extending a word (2-byte) to a long (4-byte) x86 Procedures 29 Procedure data flow puzzle ex C function body: int huh(short c, int* p, char d, int x) { *p = d; return x - c; } Translated to x86 assembly: huh: Reverse engineer the x86 huh procedure movsbl %dl, %edx and the body of the C huh function to fill huh movl %edx, (%rsi) blanks in the C function header with: • the parameter types / order; and movswl %di, %edi • the return type. subl %edi, %ecx movl %ecx, %eax retq movsbl = move sign-extending a byte to a long (4-byte) movswl = move sign-extending a word (2-byte) to a long (4-byte) x86 Procedures 30 Procedure call / stack frame example long step_up() { long v1 = 240; step_up: long v2 = increment(&v1, 61); 400509: subq $8, %rsp return v1+v2; 40050d: movq $240, (%rsp) } 400515: movq %rsp, %rdi 400518: movl $61, %esi Passes address of (in stack). 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq Uses memory through pointer.

long increment(long* p, long val) { long x = *p; long y = x + val; increment: *p = y; 4004cd: movq (%rdi), %rax return x; 4004d0: addq %rax, %rsi } 4004d3: movq %rsi, (%rdi) 4004d6: retq x86 Procedures 31 main called step_up Procedure call example (step 0) Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 40050d: movq $240, (%rsp) 0x7fdf20 400515: movq %rsp, %rdi 400518: movl $61, %esi 0x7fdf18 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf28 0x400509 4004d6: retq x86 Procedures 36 Allocate space Procedure call example (step 1) for local vars Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 240 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 400518: movl $61, %esi step_up 0x7fdf18 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf20 0x400515 4004d6: retq x86 Procedures 37 Set up args for call Procedure call example (step 2) to increment Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 240 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 400518: movl $61, %esi step_up 0x7fdf18 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 0x7fdf20 61 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf20 0x40051d 4004d6: retq x86 Procedures 38 Call increment Procedure call example (step 3) Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 240 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi 40051d: callq 4004cd step_up 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 0x7fdf20 61 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf18 0x4004cd 4004d6: retq x86 Procedures 39 Run increment Procedure call example (step 4) Stack long step_up() { Frames Memory longlong increment(long* v1 = 240; p, long val) { longlong v2 x == increment(&v1,*p; 61); • • • returnlong yv1+v2; = x + val; } *p = y; 0x40053b return x; main 0x7fdf28 step_up} : 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi 40051d: callq 4004cd step_up 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq increment %rax %rdi %rsi increment: 240 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf18 0x4004d6 4004d6: retq x86 Procedures 40 Return from increment Procedure call example (step 5a) to step_up Stack long step_up() { Frames Memory longlong increment(long* v1 = 240; p, long val) { longlong v2 x == increment(&v1,*p; 61); • • • returnlong yv1+v2; = x + val; } *p = y; 0x40053b return x; main 0x7fdf28 step_up} : 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi step_up 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 240 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf20 0x400522 4004d6: retq x86 Procedures 41 Return from increment Procedure call example (step 5b)to step_up Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi step_up 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 240 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf20 0x400522 4004d6: retq x86 Procedures 42 Prepare step_up Procedure call example (step 6) result Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi step_up 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 541 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf20 0x400526 4004d6: retq x86 Procedures 43 Deallocate space Procedure call example (step 7) for local vars Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } 0x40053b main 0x7fdf28 step_up: 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 541 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf28 0x400526 4004d6: retq x86 Procedures 44 Return from step_up Procedure call example (step 8) to main Stack long step_up() { Frames Memory long v1 = 240; long v2 = increment(&v1, 61); • • • return v1+v2; } main 0x40053b 0x7fdf28 step_up: 400509: subq $8, %rsp 301 0x7fdf20 40050d: movq $240, (%rsp) v1 400515: movq %rsp, %rdi 0x400522 0x7fdf18 400518: movl $61, %esi 40051d: callq 4004cd 400522: addq (%rsp), %rax 400526: addq $8, %rsp 40052a: retq %rax %rdi %rsi increment: 541 0x7fdf20 301 4004cd: movq (%rdi), %rax 4004d0: addq %rax, %rsi %rsp %rip 4004d3: movq %rsi, (%rdi) 0x7fdf30 0x40053b 4004d6: retq x86 Procedures 45 Implementing procedures

1. How does a caller pass arguments to a procedure? ✓

2. How does a caller receive a return value from a procedure? ✓

3. Where does a procedure store local variables? ✓

4. How does a procedure know where to return ✓ (what code to execute next when done)?

5. How do procedures share limited registers and memory? ??

x86 Procedures 46 Register saving conventions yoo calls who: Caller Callee Will register contents still be there after a procedure call? yoo: who: • • • • • • movq $12345, %rbx addq %rdi, %rbx call who ? • • • addq %rbx, %rax ret • • • ret Conventions: Caller Save Callee Save

x86 Procedures 47 x86-64 register conventions

%rax Return value – Caller saved %r8 Argument #5 – Caller saved

%rbx Callee saved %r9 Argument #6 – Caller saved

%rcx Argument #4 – Caller saved %r10 Caller saved

%rdx Argument #3 – Caller saved %r11 Caller Saved

%rsi Argument #2 – Caller saved %r12 Callee saved

%rdi Argument #1 – Caller saved %r13 Callee saved

%rsp Stack pointer %r14 Callee saved

%rbp Callee saved %r15 Callee saved

x86 Procedures 48 main called step_by(240) Callee-save example (step 0) Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 400504: pushq %rbx 0x7fdf18 400506: movq %rdi, %rbx 400509: subq $16, %rsp 0x7fdf10 40050d: movq %rdi, (%rsp) 0x7fdf08 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 3 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 240 40052b: retq %rsp %rip 0x7fdf28 0x400504 x86 Procedures 53 Save register %rbx Callee-save example (step 1) Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 400506: movq %rdi, %rbx 0x7fdf10

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 3 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 240 40052b: retq %rsp %rip 0x7fdf20 0x400506 x86 Procedures 54 Copy argument x to %rbx (step 2) for continued use after Callee-save example calling increment. Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 400506: movq %rdi, %rbx 0x7fdf10

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 240 40052b: retq %rsp %rip 0x7fdf20 0x400509 x86 Procedures 55 Set up stack frame Callee-save example (step 3) Initialize v1 Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 0x7fdf10 240

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 240 40052b: retq %rsp %rip 0x7fdf10 0x400515 x86 Procedures 56 Set up arguments Callee-save example (step 4) Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 0x7fdf10 240

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 0x400522 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 0x7fdf10 61 40052b: retq %rsp %rip 0x7fdf10 0x40051d x86 Procedures 57 Call, execute, and return Callee-save example (step 5) from increment Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 0x7fdf10 301

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 0x400522 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 240 0x7fdf10 301 40052b: retq %rsp %rip 0x7fdf10 0x400522 x86 Procedures 58 Prepare return value Callee-save example (step 6) Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 0x7fdf10 301

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 0x400522 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 480 0x7fdf10 301 40052b: retq %rsp %rip 0x7fdf10 0x400525 x86 Procedures 59 Clean up stack frame Callee-save example (step 7) Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 0x7fdf10 301

400509: subq $16, %rsp step_by 40050d: movq %rdi, (%rsp) 0x7fdf08 0x400522 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 240 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 480 0x7fdf10 301 40052b: retq %rsp %rip 0x7fdf20 0x400529 x86 Procedures 60 Restore register %rbx Callee-save example (step 8) Ready to return Stack long step_by(long x) { Frames Memory long v1 = x; long v2 = increment(&v1, 61); • • • return x + v2; } main 0x7fdf28 0x40053b step_by: 0x7fdf20 3 400504: pushq %rbx 0x7fdf18 for alignment 400506: movq %rdi, %rbx 400509: subq $16, %rsp 0x7fdf10 301 40050d: movq %rdi, (%rsp) 0x7fdf08 0x400522 400515: movq %rsp, %rdi 400518: movl $61, %esi %rbx 40051d: callq 4004cd 3 400522: addq %rbx, %rax 400525: addq $16, %rsp %rax %rdi %rsi 400529: popq %rbx 480 0x7fdf10 301 40052b: retq %rsp %rip 0x7fdf28 0x40052b x86 Procedures 61 Recursion example: code long pcount(unsigned long x) { if (x == 0) { return 0; } else { return (x & 1) + pcount(x >> 1); } } pcount: 4005dd: movl $0, %eax base case/ 4005e2: testq %rdi, %rdi condition 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx recursive 4005e8: movq %rdi, %rbx case 4005eb: andl $1, %ebx 4005ee: shrq %rdi x&1 in %rbx 4005f1: callq pcount across call 4005f6: addq %rbx, %rax save/restore 4005f9: popq %rbx %rbx (callee-save) .L6: 4005fa: rep 4005fb: retq x86 Procedures 62 Recursion Example: pcount(2) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 return (x & 1) + pcount(x >> 1); 0x7fdf28 } 0x7fdf20 } 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 2 42 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf38 0x4005dd 4005fb: retq x86 Procedures 67 Recursion Example: pcount(2) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 return (x & 1) + pcount(x >> 1); 0x7fdf28 } pc(2) 0x7fdf20 } 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 2 42 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf38 0x4005e7 4005fb: retq x86 Procedures 68 Recursion Example: pcount(2) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 } pc(2) 0x7fdf20 } 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 2 2 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf30 0x4005eb 4005fb: retq x86 Procedures 69 Recursion Example: pcount(2) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 } pc(2) 0x7fdf20 } 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 1 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf30 0x4005f1 4005fb: retq x86 Procedures 70 Recursion Example: pcount(2) → pcount(1) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 pc(2) 0x4005f6 } 0x7fdf20 } 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 1 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf28 0x4005dd 4005fb: retq x86 Procedures 71 Recursion Example: pcount(2) → pcount(1) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 }} 0x7fdf18 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 1 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf28 0x4005e7 4005fb: retq x86 Procedures 72 Recursion Example: pcount(2) → pcount(1) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 1 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf20 0x4005eb 4005fb: retq x86 Procedures 73 Recursion Example: pcount(2) → pcount(1) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn ((xx && 11)) ++ pcountpcount((xx >>>> 11));; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf20 0x4005f1 4005fb: retq x86 Procedures 74 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount((xx >>>> 11));; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 0x4005f6 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf18 0x4005dd 4005fb: retq x86 Procedures 75 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames longlong pcountpcount(unsigned(unsigned longlong x)x) {{ Memory ifif (x(x ==== 0)0) {{ if (x == 0) { 0x7fdf38 0x4006ed return 0; main returnreturn 0;0; } else { }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 return (x & 1) + pcount(x >> 1); pc(2) 0x4005f6 } }} 0x7fdf20 0 }} } 0x7fdf18 0x4005f6 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf18 0x4005fa 4005fb: retq x86 Procedures 76 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames longlong pcountpcount(unsigned(unsigned longlong x)x) {{ Memory ifif (x(x ==== 0)0) {{ if (x == 0) { 0x7fdf38 0x4006ed return 0; main returnreturn 0;0; } else { }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 return (x & 1) + pcount(x >> 1); pc(2) 0x4005f6 } }} 0x7fdf20 0 }} } 0x7fdf18 0x4005f6 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf20 0x4005f6 4005fb: retq x86 Procedures 77 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 0x4005f6 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 0 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf20 0x4005f6 4005fb: retq x86 Procedures 78 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 0x4005f6 pcount: pc(1) 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 1 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf20 0x4005f9 4005fb: retq x86 Procedures 79 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf28 0x4005fa 4005fb: retq x86 Procedures 80 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames long pcount(unsigned long x) { Memory ifif (x(x ==== 0)0) {{ 0x7fdf38 0x4006ed returnreturn 0;0; main }} elseelse {{ 0x7fdf30 42 returnreturn (x(x && 1)1) ++ pcountpcount(x(x >>>> 1)1);; 0x7fdf28 pc(2) 0x4005f6 } } 0x7fdf20 0 }} 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf30 0x4005f6 4005fb: retq x86 Procedures 81 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 pc(2) 0x4005f6 } 0x7fdf20 0 } 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf30 0x4005f6 4005fb: retq x86 Procedures 82 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 pc(2) 0x4005f6 } 0x7fdf20 0 } 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 0 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf30 0x4005f9 4005fb: retq x86 Procedures 83 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { 0x7fdf38 0x4006ed return 0; main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 0x4005f6 } 0x7fdf20 0 } 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 42 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf38 0x4005f9 4005fb: retq x86 Procedures 84 Recursion Example: pcount(2) → pcount(1) → pcount(0) Stack long pcount(unsigned long x) { Frames Memory if (x == 0) { return 0; 0x7fdf38 0x4006ed main } else { 0x7fdf30 42 return (x & 1) + pcount(x >> 1); 0x7fdf28 0x4005f6 } 0x7fdf20 0 } 0x7fdf18 0x4005f6 pcount: 0x7fdf10 4005dd: movl $0, %eax 4005e2: testq %rdi, %rdi 0x7fdf08 4005e5: je 4005fa <.L6> 4005e7: pushq %rbx 4005e8: movq %rdi, %rbx 4005eb: andl $1, %ebx 4005ee: shrq %rdi 4005f1: callq pcount %rax %rdi %rbx 4005f6: addq %rbx, %rax 1 0 42 4005f9: popq %rbx %rsp %rip .L6: 4005fa: rep 0x7fdf40 0x4006ed 4005fb: retq x86 Procedures 85 Stack storage example optional (1) long int call_proc() call_proc: { subq $32,%rsp long x1 = 1; movq $1,16(%rsp) # x1 int x2 = 2; movl $2,24(%rsp) # x2 short x3 = 3; movw $3,28(%rsp) # x3 char x4 = 4; movb $4,31(%rsp) # x4 proc(x1, &x1, x2, &x2, • • • x3, &x3, x4, &x4); return (x1+x2)*(x3-x4); }

Return address to caller of call_proc ←%rsp

x86 Procedures 86 Stack storage example optional (2) Allocate local vars long int call_proc() call_proc: { subq $32,%rsp long x1 = 1; movq $1,16(%rsp) # x1 int x2 = 2; movl $2,24(%rsp) # x2 short x3 = 3; movw $3,28(%rsp) # x3 char x4 = 4; movb $4,31(%rsp) # x4 proc(x1, &x1, x2, &x2, • • • x3, &x3, x4, &x4); return (x1+x2)*(x3-x4); }

Return address to caller of call_proc x4 x3 x2 24 x1 16 8 ←%rsp

x86 Procedures 87 Stack storage example optional (3) setup args to proc long int call_proc() call_proc: { • • • long x1 = 1; leaq 24(%rsp),%rcx # &x2 int x2 = 2; leaq 16(%rsp),%rsi # &x1 short x3 = 3; leaq 31(%rsp),%rax # &x4 char x4 = 4; movq %rax,8(%rsp) # ... proc(x1, &x1, x2, &x2, movl $4,(%rsp) # 4 x3, &x3, x4, &x4); leaq 28(%rsp),%r9 # &x3 return (x1+x2)*(x3-x4); movl $3,%r8d # 3 } movl $2,%edx # 2 movq $1,%rdi # 1 Return address to caller of call_proc call proc x4 x3 x2 24 • • • x1 16 Arg 8 8 Arguments passed in (in order): %rdi, %rsi, %rdx, %rcx, %r8, %r9 Arg 7 ←%rsp

x86 Procedures 88 Stack storage example optional (4) after call to proc long int call_proc() call_proc: { • • • long x1 = 1; movswl 28(%rsp),%eax # x3 int x2 = 2; movsbl 31(%rsp),%edx # x4 short x3 = 3; subl %edx,%eax # x3-x4 char x4 = 4; cltq # sign-extend %eax->%rax proc(x1, &x1, x2, &x2, movslq 24(%rsp),%rdx # x2 x3, &x3, x4, &x4); addq 16(%rsp),%rdx # x1+x2 return (x1+x2)*(x3-x4); imulq %rdx,%rax # * } addq $32,%rsp ret Return address to caller of call_proc x4 x3 x2 24 x1 16 Arg 8 8 Arg 7 ←%rsp

x86 Procedures 89 Stack storage example optional (5) deallocate local vars long int call_proc() call_proc: { • • • long x1 = 1; movswl 28(%rsp),%eax int x2 = 2; movsbl 31(%rsp),%edx short x3 = 3; subl %edx,%eax char x4 = 4; cltq proc(x1, &x1, x2, &x2, movslq 24(%rsp),%rdx x3, &x3, x4, &x4); addq 16(%rsp),%rdx return (x1+x2)*(x3-x4); imulq %rdx,%rax } addq $32,%rsp ret Return address to caller of call_proc ←%rsp

x86 Procedures 90 Procedure Summary call, ret, push, pop … Stack discipline fits procedure call / return.* Caller If P calls Q: Q (and calls by Q) returns before P Frame Conventions support arbitrary function calls. Extra Arguments to callee Register-save conventions. Stack frame saves extra args or local variables. Return Address Result returned in %rax

%rax Return value – Caller saved %r8 Argument #5 – Caller saved Saved Registers + %rbx %r9 Callee saved Argument #6 – Caller saved Callee Local Variables %rcx Argument #4 – Caller saved %r10 Caller saved Frame

%rdx Argument #3 – Caller saved %r11 Caller Saved

%rsi Argument #2 – Caller saved %r12 Callee saved Extra Arguments %rdi Argument #1 – Caller saved %r13 Callee saved Stack pointer %rsp for next call %rsp Stack pointer %r14 Callee saved

%rbp Callee saved %r15 Callee saved 128-byte red zone

*Take CS 251 to learn about languages where a simple stack does not suffice. x86 Procedures 91