Readings for Next 3 Lectures ‣ Textbook CPSC 213 •Procedures - 3.7 •Out-of-Bounds Memory References and Buffer Overflow - 3.12 Introduction to Computer Systems Unit 1e Procedures and the Stack 1 2 Local Variables of a Procedure Dynamic Allocation of Locals public class A { void b () { void b () { public static void b () { int l0 = 0; int l0 = 0; int l0 = 0; int l1 = 1; int l1 = 1; int l1 = 1; } } } } void foo () { void foo () { b (); b (); public class Foo { } } C static void foo () { A.b (); ‣ Lifetime of a local } } Java • starts when procedure is called and ends when procedure returns • allocation and deallocation are implicitly part of procedure call ‣ Should we allocate locals from the heap? ‣ Can l0 and l1 be allocated statically (i.e., by the compiler)? • the heap is where Java new and C malloc, the other kind of dynamic storage • [G] Yes • could we use the heap for locals? • [Y] Yes, but only by eliminating recursion - [G] Yes • [B] Yes, but more than just recursion must be eliminated - [Y] Yes, but it would be less efficient to do so • [R] No, no change to the language can make this possible - [R] No 3 4
Procedure Storage Needs Stack vs. Heap address memory 0x00000000 frame ‣ frame ‣ split memory into two pieces arg 0 pointer •arguments •heap grows down arg 1 arguments Frame C sp 0x4fea •local variables •stack grows up arg 2 stack Frame B •saved registers ‣ move stack pointer up to sp 0x4 fg 0 local 0 - return address smaller number when add Frame A sp 0x4 fg 6 local 1 local variables ‣ access through offsets from top frame Struct A sp 0x5000 local 2 heap •just like structs with base ‣ but within frame, offsets still go down Struct B ret addr saved registers Struct C 0x1000 pointer pointer ‣ simple example local 0 Frame A 0x1000 local 0 ptr + 0 local variables •two local vars 0x1004 local 1 local 1 ptr + 4 •saved return address ret addr 0x1008 saved register ret addr ptr + 8 address 0x fgfgfgfg 5 6 Runtime Stack and Activation Frames Compiling a Procedure Call / Return ‣ Runtime Stack ‣ Procedure Prologue •like the heap, but optimized for procedures •code generated by compiler to execute just before procedure starts •one per thread •allocates activation frame and changes stack pointer •grows “up” from lower addresses to higher ones - subtract frame size from the stack pointer r5 •possibly saves some register values ‣ Activation Frame ‣ Procedure Epilogue •an “object” that stores variables in procedure’s local scope - local variables and formal arguments of the procedure •code generated by compiler to execute just before a procedure returns - temporary values such as saved registers (e.g., return address) and link to previous frame •possibly restores some saved register values •size and relative position of variables within frame is known statically •deallocates activation frame and restore stack pointer ‣ Stack pointer - add frame size to stack pointer r5 •register reserved to point to activation frame of current procedure •we will use r5 •accessing locals and args static offset from r5, the stack pointer (sp) - locals are accessed exactly like instance variables; r5 is pointer to containing “object” 7 8
Snippet 8 - An example Creating the stack 1 allocate bar frame (1) foo: deca r5 # sp-=4 ‣ Every thread starts with a hidden procedure st r6, 0x0(r5) # save r6 to stack save r6 • its name is start (or sometimes something like crt0) ld $b, r0 # address of b () 2 ‣ The start procedure gpc r6 # r6 = pc call b() inca r6 # r6 = r6 + 4 • allocates memory for stack j 0x0(r0) # goto b () • initializes the stack pointer ld 0x0(r5), r6 # restore r6 from stack restore r6 6 • calls main() (or whatever the thread’s first procedure is) inca r5 # sp+=4 dealloc bar frame (1) j 0x0(r6) # return ‣ For example in Snippet 8 return • the “main” procedure is “foo” 3 b: ld $0xfffffff8, r0 # r0 = -8 (frames size) allocate bar frame (2) • we’ll statically allocate stack at address 0x1000 to keep simulation simple add r0, r5 # create frame on stack .pos 0x100 ld $0, r0 # r0 = 0 start: ld $0x1028, r0 # base of stack 4 st r0, 0x0(r5) # l0 = 0 mov r0, r5 # init stack pointer body ld $0x1, r0 # r0 = 1 ld $foo, r0 # r0 = & foo () st r0, 0x4(r5) # l1 = 1 gpc r6 # r6 = pc .pos 0x1000 inca r6 # r6 = r6 + 4 stack: .long 0x00000000 j 0x0(r0) # goto foo () 5 ld $0x8, r0 # r0 = 8 = (frame size) dealloc bar frame (2) .long 0x00000000 halt add r0, r5 # teardown frame return ... j 0x0(r6) # return 9 10 Question Diagram of Stack for this Example void three () { sp 1964 Frame Three int i; before jump to ptr + 0 local i void foo () { void one () { void two () { void three () { int j; // r5 = 2000 int i; int i; int i; int k; three() code: ptr + 4 local j one (); int j; int j; } save r6 to stack } two (); int k; ptr + 8 local k then set r6 to } three (); } void two () { } ptr + 12 ret addr: $tworet $threeret int i; int j; Frame Two sp 1980 before jump to ‣ What is the value of r5 when executing in the procedure three() three (); ptr + 0 local i two() code: save } • [R] 1964 r6 to stack then ptr + 4 local j void one () { • [G] 2032 set r6 to $tworet int i; ptr + 8 ret addr: $oneret • [B] 1968 before jump to two (); Frame One sp 1992 • [Y] None of the above } one() code: save local i • [ALL] I don’t know ptr + 0 r6 to stack then void foo () { ret addr: $fooret set r6 to $oneret ptr + 4 // r5 = 2000 one (); } r6 is$fooret Frame Foo sp 2000 11 12
Arguments and Return Value Snippet 9 public class A { int add (int a, int b) { ‣ return value static int add (int a, int b) { return a+b; return a+b; } •in register, typically r0 } ‣ arguments } int s; •in registers or on stack public class foo { void foo () { static int s; s = add (1,2); static void foo () { } C s = add (1,2); } Java } ‣ Formal arguments • act as local variables for called procedure • supplied values by caller ‣ Actual arguments • values supplied by caller • bound to formal arguments for call 13 14 Arguments in Registers (S9-args-regs.s) Arguments on Stack (S9-args-stack.s) .pos 0x200 .pos 0x200 foo: deca r5 # sp-=4 foo: deca r5 # sp-=4 st r6, 0x0(r5) # save r6 to stack st r6, 0x0(r5) # save r6 to stack ld $0x1, r0 # arg0 (r0) = 1 ld $0x2, r0 # r0 = 2 ld $0x2, r1 # arg1 (r1) = 2 deca r5 # sp-=4 st r0, 0x0(r5) # save arg1 on stack ld $add, r3 # address of add () ld $0x1, r0 # r0 = 1 gpc r6 # r6 = pc deca r5 # sp-=4 inca r6 # r6 = r6 + 4 st r0, 0x0(r5) # save arg0 on stack j 0x0(r3) # goto add () ld $add, r3 # address of add () ld $s, r1 # r1 = address of s gpc r6 # r6 = pc st r0, 0x0(r1) # s = add (1,2) inca r6 # r6 = r6 + 4 ld 0x0(r5), r6 # restore r6 from stack j 0x0(r3) # goto add () inca r5 # discard arg0 from stack inca r5 # sp+=4 inca r5 # discard arg1 from stack j 0x0(r6) # return ld $s, r1 # r1 = address of s .pos 0x300 st r0, 0x0(r1) # s = add (1,2) add: add r1, r0 # return (r0) = a (r0) + b (r1) ld 0x0(r5), r6 # restore r6 from stack j 0x0(r6) # return inca r5 # sp+=4 j 0x0(r6) # return .pos 0x300 add: ld 0x0(r5), r0 # r0 = arg0 ld 0x4(r5), r1 # r1 = arg1 add r1, r0 # return (r0) = a (r0) + b (r1) j 0x0(r6) # return 15 16
Recommend
More recommend