z = c(); } } int a() { int c() { y = b(); } } 1 The call - - PowerPoint PPT Presentation

z c
SMART_READER_LITE
LIVE PREVIEW

z = c(); } } int a() { int c() { y = b(); } } 1 The call - - PowerPoint PPT Presentation

int main( ) { int b() { x = a(); z = c(); } } int a() { int c() { y = b(); } } 1 The call tree: main calls a main a calls b b calls c a c returns to b b returns to a b a returns to main c 2 Partial assembly code for main()


slide-1
SLIDE 1

int main( ) { x = a(); } int a() { y = b(); } int b() { z = c(); } int c() { }

1

slide-2
SLIDE 2

main calls a a calls b b calls c c returns to b b returns to a a returns to main The call tree:

2

main a b c

slide-3
SLIDE 3

Partial assembly code for main() and a()

main: . . branch a # call a_rtn: copy x, a_rtn_value . . a: . . branch b # call b_rtn: copy y, b_rtn_value . . branch a_rtn # return from a

3

slide-4
SLIDE 4

Modified assembly code for main() and a()

main: . branch a # call a_rtn1: copy x, a_rtn_value . branch a # another call to a a_rtn2: copy x, a_rtn_value . a: . . branch b # call b_rtn: copy y, b_rtn_value . . branch # return from a

4

slide-5
SLIDE 5

Different example: Recursion

int main( ) { x = a( ); } int a( ) { z = a( ); }

5

main a

slide-6
SLIDE 6

main: la a_rtn, rtn1 branch a # call rtn1: # copy out return value a: # recursive call la a_rtn, rtn2 branch a rtn2: # copy out return value . . branch (a_rtn)

6

slide-7
SLIDE 7

To make this work, the code needs to

– just before each call, save the return address – before each return, get and use the most recently saved return address

The data structure required is called a stack.

7

slide-8
SLIDE 8

A stack organizes data

  • LIFO – Last In First Out
  • push puts data into the stack
  • pop takes data out of the stack

8

slide-9
SLIDE 9

9

The initial state of the stack: it is empty. After a first push of a

  • nto the stack.

a

slide-10
SLIDE 10

10

After a third push of c

  • nto the stack.

a a b b c

After a second push of b

  • nto the stack.
slide-11
SLIDE 11

11

Push d. a a b b d The stack returns c due to a pop operation.

slide-12
SLIDE 12

12

Pop returns b. a a b Pop returns d.

slide-13
SLIDE 13

Different example: Recursion

main: la a_rtn, rtn1 branch a # call rtn1: # copy out return value a: push a_rtn # recursive call la a_rtn, rtn2 branch a rtn2: # copy out return value . . pop a_rtn branch (a_rtn)

13

slide-14
SLIDE 14

The problem of overwritten return addresses is solved with a stack. The same problem exists with

– parameters – variables local to a function

The solution bundles all these saved/restored values into a single set to be pushed/popped. The set of items is called an activation record (AR) or stack frame.

14

slide-15
SLIDE 15

Important detail: A compiler cannot always know if there is recursion in a program! Consider separate compilation. In file 1:

int a() { z = b(); }

In file 2:

int b() { x = a(); }

15

slide-16
SLIDE 16

Memory Allocation

  • What is in memory?
  • When is it in memory?

And, when is or was the memory space allocated?

  • Where within memory is it?

16

slide-17
SLIDE 17

What and Where are

– program code (machine code) – global variables (data) – stack – heap

Each can be thought of as residing in its own, separate section of memory. These sections are often identified as segments.

17

slide-18
SLIDE 18

When is the memory space allocated?

  • static

The compiler knows details of the allocation, so causes the assembler to allocate the space. This implies that the memory image created by the assembler contains the memory space.

  • dynamic

The allocation of memory space occurs while the program executes.

18

slide-19
SLIDE 19

Program Code The program's source code is compiled and then it is assembled to produce machine code (memory image). To run the program, the memory image is placed (copied) into memory. Therefore, the code is already in memory, and classified as a static allocation.

19

slide-20
SLIDE 20

int x, y, z; /* global variables */ int main() { }

Both the compiler, and therefore the assembler, know exactly how much memory space is needed. When the program (memory image) is placed into memory, the allocation of memory for the integers has been completed. It is therefore classified as a static allocation.

20

slide-21
SLIDE 21

#define MAX 4 int array[MAX]; /* global */ int main() { }

21

slide-22
SLIDE 22

char *stringptr; stringptr = (char *) malloc(bytes_needed + 1);

22

slide-23
SLIDE 23

23

Consider space for the activation record: a: push a_rtn . . la a_rtn, rtn2 branch a rtn2: . . pop a_rtn branch (a_rtn)

slide-24
SLIDE 24

int fcn(int y) { } int main() { int x, y; y = 20; x = fcn(y); }

24

slide-25
SLIDE 25

Summary

  • Static

– program code – global variables

  • Dynamic

– anything that goes onto the stack, such as parameters and return address – memory allocated as the program is running, such as allocation done with malloc()

25