800 likes | 921 Views
Procedure Call and Array. Outline. Data manipulation Control structure Suggested reading Chap 3.7, 3.8. Procedure. In high level programming languages Parameter passing (actual vs. formal) Return value Control transfer Allocate space for local variables on entry
E N D
Outline • Data manipulation • Control structure • Suggested reading • Chap 3.7, 3.8
Procedure • In high level programming languages • Parameter passing (actual vs. formal) • Return value • Control transfer • Allocate space for local variables on entry • Deallocate space for local variables on exit
Procedure Implementation • Stack frame • A fixed register is used to hold the return value • Simple instructions for control transferring • Register usage • Calling convention Convention:约定 Frame: 帧,结构
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
Call Chain & Stack Frames Main { C(); A() ; } A() { B() ; } B() { C() ; }
%ebp %esp Frame Structure • A stack frame is delimited by • The frame pointer %ebp • The stack pointer %esp • The stack pointer can move when the procedure is executing • Frame pointer relative accessing
Old ebp Old ebp Frame Structure • Frames are chained Old ebp %ebp %esp
Caller and Callee Caller() { call callee (argument1, … , argumentn); }
Register Usage • Caller saved registers • %eax, %edx, %ecx • Saved by caller • Callee can use these registers freely • The contents in these registers may be changed after return • Caller must restore them if it tries to use them after calling
Register Usage • Callee saved registers • %ebx, %esi, %edi • Callee must save them before using • Callee must restore them before return
Calling Convention • Save caller save registers (%eax, %edx, %ecx) • Push actual arguments from right to left • Call instruction • Save return address • Transfer control to callee
Passing Parameters pushl argument n ……… Argument n %esp
Passing Parameters pushl argument n …………… pushl argument 1 ……… Argument n ……… Argument 1 %esp
Passing Parameters pushl argument n …………… pushl argument 1 call callee ……… Argument n ……… Argument 1 Return address %esp
Call Instruction P172 • call label (direct) • call *operand (indirect) • Save return address in the stack • Jump to the entry to callee
Initialize Stack frame pushl %ebp movl %esp, %ebp save callee saved register adjust %esp to allocate space for local variables and temporaries
Destruct a Frame restore callee saved registers movl %ebp, %esp popl %ebp ret Integeral return value is in the %eax restore callee saved registers leave ret
Example P175 Figure 3.18 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 P175 Figure 3.18 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 P174 1 leal -4(%ebp),%eax Compute &arg2 2 pushl %eax Push &arg2 Stack frame for caller
%ebp %esp Parameter Passing P174 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 P174 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 Call Instruction P174 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 P176 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 3 pushl %ebx Save %ebx Stack frame for caller Stack frame for swap_add
%esp %ebp Body code in swap_add 5 movl 8(%ebp),%edx Get xp Stack frame for caller %edx xp(=&arg1=%ebp+16) Stack frame for swap_add
%esp %ebp Body code in swap_add 5 movl 8(%ebp),%edx Get xp 6 movl 12(%ebp),%ecx Get yp Stack frame for caller %edx xp(=&arg1=%ebp+16) %ecx yp(=&arg2=%ebp+20) Stack frame for swap_add
%esp %ebp Body code in swap_add 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 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 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 P178 Figure 3.20 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 P179 Figure 3.21 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
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