600 likes | 770 Views
Procedure Call. Procedure/Function Implementation. Invoke callee: call (new instructions) Return to caller: ret (new instructions) Passing data: stack , register Registers: calling convention Local variable: stack. Local Variable. Why not store local variables in registers ?
E N D
Procedure/Function Implementation • Invoke callee: call (new instructions) • Return to caller: ret (new instructions) • Passing data: stack, register • Registers: calling convention • Local variable: stack
Local Variable • Why not store local variables in registers ? • No enough registers • Array and structures (e.g., a[2]) • Need address (e.g., &a)
%ebp %esp Local Variable • Allocation • Below saved regs or old %ebp • move/sub %esp, (e.g., subl $4, %esp) • De-allocation • move/add %esp, (e.g., addl $4, %esp) • Usage • Relative to %esp/%ebp, (e.g., movl %eax, 8(%esp))
%ebp %esp Put it Together
%ebp %esp Put it Together 1. Save caller-save registers (%eax, %edx, %ecx)
%ebp %esp Put it Together 1. Save caller-save registers (%eax, %edx, %ecx) 2. Push actual arguments from right to left
%ebp %esp Put it Together 1. Save caller-save registers (%eax, %edx, %ecx) 2. Push actual arguments from right to left 3. Call instruction • Save return address • Transfer control to callee
%ebp %esp Put it Together 4. Save caller %ebp
%esp / %ebp Put it Together 4. Save caller %ebp 5. Set callee %ebp
%ebp %esp Put it Together 4. Save caller %ebp 5. Set callee %ebp 6. Save callee-save registers (%ebx, %edi, %esi)
%ebp %esp Put it Together 4. Save caller %ebp 5. Set callee %ebp 6. Save callee-save registers (%ebx, %edi, %esi) 7. Allocate space for local variable
%ebp %esp Put it Together . . . n-4. save return value in %eax
%ebp %esp Put it Together . . . n-4. save return value in %eax n-3. de-allocate local variable
%esp / %ebp Put it Together . . . n-4. save return value in %eax n-3. de-allocate local variable n-2. Restore callee-save registers
%ebp %esp Put it Together . . . n-4. save return value in %eax n-3. de-allocate local variable n-2. Restore callee-save registers n-1. Restore caller %ebp
%ebp %esp Put it Together . . . n-4. save return value in %eax n-3. de-allocate local variable n-2. Restore callee-save registers n-1. Restore caller %ebp n. Ret instruction • pop return address • Transfer control to caller
Example 1 int swap_add(int *xp, int *yp) 2 { 3 int x = *xp; 4 int y = *yp; 5 6 *xp = y; 7 *yp = x; 8 return x + y; 9 } 10
Example 11 int caller() 12 { 13 int arg1 = 534; 14 int arg2 = 1057; 15 int sum = swap_add(&arg1, &arg2); 16 int diff = arg1 - arg2; 17 18 return sum * diff; 19 }
%ebp %esp Example Stack frame for caller Before int sum = swap_add(&arg1, &arg2);
%ebp %esp Parameter Passing 1 leal -4(%ebp),%eax Compute &arg2 2 pushl %eax Push &arg2 Stack frame for caller
%ebp %esp Parameter Passing 1 leal -4(%ebp),%eax Compute &arg2 2 pushl %eax Push &arg2 3 leal -8(%ebp),%eax Compute &arg1 4 pushl %eax Push &arg1 Stack frame for caller
%ebp %esp Call Instruction 1 leal -4(%ebp),%eax Compute &arg2 2 pushl %eax Push &arg2 3 leal -8(%ebp),%eax Compute &arg1 4 pushl %eax Push &arg1 5 call swap_add Call the swap_add function Stack frame for caller
%ebp %esp Setup code in swap_add swap_add: 1 pushl %ebp Save old %ebp Stack frame for caller
%esp Setup code in swap_add swap_add: 1 pushl %ebp Save old %ebp 2 movl %esp,%ebp Set %ebp as frame pointer Stack frame for caller %ebp Stack frame for swap_add
%esp %ebp Setup code in swap_add swap_add: 1 pushl %ebp Save old %ebp 2 movl %esp,%ebp Set %ebp as frame pointer 3pushl %ebx Save %ebx Stack frame for caller Stack frame for swap_add
%esp %ebp Body code in swap_add Stack frame for caller 5 movl 8(%ebp),%edx Get xp %edx xp(=&arg1=%ebp+16) Stack frame for swap_add
%esp %ebp Body code in swap_add Stack frame for caller 5 movl 8(%ebp),%edx Get xp 6 movl 12(%ebp),%ecx Get yp %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add
%esp %ebp Body code in swap_add Stack frame for caller 5 movl 8(%ebp),%edx Get xp 6 movl 12(%ebp),%ecx Get yp 7 movl (%edx),%ebx Get x 8 movl (%ecx),%eax Get y %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx 534 %eax 1057
%esp %ebp Body code in swap_add 9 movl %eax, (%edx) Store y at *xp Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx 534 %eax 1057
%esp %ebp Body code in swap_add 9 movl %eax, (%edx) Store y at *xp 10 movl %ebx, (%ecx) Store x at *yp Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx 534 %eax 1057
%esp %ebp Body code in swap_add 9 movl %eax, (%edx) Store y at *xp 10 movl %ebx, (%ecx) Store x at *yp 11 addl %ebx,%eax Set return value = x+y Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx 534 %eax 1591
%ebp Finishing code in swap_add 12 popl %ebx Restore %ebx Stack frame for caller %edx xp(=&arg1=%ebp+16) %esp %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx original value %eax 1591
%ebp Finishing code in swap_add 12 popl %ebx Restore %ebx 13 movl %ebp, %esp Restore %esp Stack frame for caller %edx xp(=&arg1=%ebp+16) %esp %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add %ebx original value %eax 1591
%ebp %esp Finishing code in swap_add 12 popl %ebx Restore %ebx 13 movl %ebp, %esp Restore %esp 14 popl %ebp Restore %ebp Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) %ebx original value %eax 1591
%ebp %esp Finishing code in swap_add • 12 popl %ebx Restore %ebx • 13 movl %ebp, %esp Restore %esp • 14 popl %ebp Restore %ebp • 15 ret Return to caller • Call by value Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) %ebx original value %eax 1591
Recursion Example 1 int fib_rec(int n) 2 { 3 int prev_val, val; 4 5 if (n <= 2) 6 return 1; 7 prev_val = fib_rec(n-2); 8 val = fib_rec(n-1); 9 return prev_val + val; 10 }
Setup code 1 fib_rec: 2 pushl %ebp Save old %ebp 3 movl %esp,%ebp Set %ebp as frame pointer 4 subl $16,%esp Allocate 16 bytes on stack 5 pushl %esi Save %esi (offset -20) 6 pushl %ebx Save %ebx (offset -24)
%ebp %esp Recursion Stack frame
Body code 7 movl 8(%ebp),%ebx Get n 8 cmpl $2,%ebx Compare n:2 9 jle .L24 if <=, goto terminate 10 addl $-12,%esp Allocate 12 bytes on stack 11 leal -2(%ebx),%eax Compute n-2 12 pushl %eax Push as argument 13 call fib_rec Call fib_rec(n-2)
%ebp %esp Recursion Stack frame
Body code 14 movl %eax,%esi Store result in %esi 15 addl $-12,%esp Allocate 12 bytes to stack 16 leal -1(%ebx),%eax Compute n-1 17 pushl %eax Push as argument 18 call fib_rec Call fib_rec(n-1) 19 addl %esi,%eax Compute val+nval 20 jmp .L25 Go to done
%ebp %esp Stack frame
Terminal condition 21 .L24: terminate: 22 movl $1,%eax Return value 1
Finishing code 23 .L25: done: 24 leal -24(%ebp),%esp Set stack to offset -24 25 popl %ebx Restore %ebx 26 popl %esi Restore %esi 27 movl %ebp,%esp Restore stack pointer 28 popl %ebp Restore %ebp 29 ret Return
Permutation • #include <stdio.h> • void permute(int a[], int n, int k) • { • int i; • if (k == 0) { • for ( i=0; i<n; i++) • printf("%d", a[i]); • printf("\n"); • }
Permutation • for ( i=0; i<=k; i++) { • int tempi = a[i], tempk = a[k]; • a[i] = tempk ; a[k] = tempi; • permute(a,n,k-1); • a[i] = tempi; a[k] = tempk; • } • }
Permutation .file"permute.c" .section .rdata,"dr" LC0: .ascii "%d\0" .text .globl _permute .def_permute;.scl2;.type32;.endef
Permutation _permute: pushl%ebp movl%esp, %ebp subl $40, %esp cmpl$0, 16(%ebp) # k == 0 ? jne L2 movl$0, -12(%ebp) # i = 0 jmp L3
Permutation L4: movl-12(%ebp), %eax # i sall $2, %eax # 4*i addl 8(%ebp), %eax # a+4*i movl(%eax), %eax # a[i] movl%eax, 4(%esp) # pushl a[i] movl$LC0, (%esp) # pushl “%d\n” call _printf addl $1, -12(%ebp) # i = i + 1