52
Procedures and the Call Stack Topics Procedures Call stack Procedure/stack instructions Calling conventions Register-saving conventions

Procedures and the Call Stack - Wellesley College

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

ProceduresandtheCallStack

Topics• Procedures• Callstack• Procedure/stack instructions• Callingconventions• Register-saving conventions

WhyProcedures?Whyfunctions?Whymethods?

ProceduralAbstraction

int contains_char(char* haystack, char needle) {while (*haystack != '\0') {

if (*haystack == needle) return 1;haystack++;

}return 0;

}

Implementing Procedures

Howdoesacallerpassarguments toaprocedure?

Howdoesacallergetareturnvaluefromaprocedure?

Wheredoesaprocedurestorelocalvariables?

Howdoesaprocedureknowwheretoreturn(whatcodetoexecutenextwhendone)?

Howdoproceduressharelimitedregistersandmemory?

3

CallChainyoo(…){

••who();••

}

who(…){

• • •ru();• • •ru();• • •

}

ru(…){

•••

}

yoo

who

ru

ExampleCallChain

ru

4

FirstTry(broken)

yoo:

jmp whoback:

stop:

who:

done:jmp back

WhatifIwanttocallafunctionmultipletimes?

FirstTry(broken)

who:

jmp ruback2:

jmp ruback2:

stop:

ru:

done:jmp back2

12

65 3,7

89

4

WhatifIwanttocallafunctionmultipletimes?

Implementing Procedures

Howdoesacallerpassarguments toaprocedure?

Howdoesacallergetareturnvaluefromaprocedure?

Wheredoesaprocedurestorelocalvariables?

Howdoesaprocedureknowwheretoreturn(whatcodetoexecutenextwhendone)?

Howdoproceduressharelimitedregistersandmemory?

7

Alltheseneedseparatestorage percall!(notjustperprocedure)

Addr Perm Contents Managedby Initialized

2N-1 Stack RW Procedurecontext Compiler Run-time

Heap RW Dynamicdata structures

Programmer,malloc/free,new/GC

Run-time

Statics RW Globalvariables/staticdatastructures

Compiler/Assembler/Linker Startup

Literals R Stringliterals Compiler/Assembler/Linker Startup

Text X Instructions Compiler/Assembler/Linker Startup

0

MemoryLayout

CallStack

Weseex86organization.Detailsdiffer acrossarchitectures, butbigideasareshared.

RegionofmemoryManagedwithstackdiscipline

%esp holdslowest stackaddress(address of"top"element)

StackPointer:%esp

stackgrowstoward

lower addresses

higheraddresses

Stack“Top”

Stack“Bottom”

9

(not extra-sensoryperception)

IA32CallStack: Push

pushl Src

Stack“Top”

Stack“Bottom”

StackPointer:%esp

10

stackgrowstoward

lower addresses

higheraddresses

IA32CallStack:Push

pushl Src1. Fetchvalue fromSrc2. Decrement%esp by4 (why4?)3. Storevalueatnewaddress

givenby%esp

Stack“Top”

Stack“Bottom”

-4

11

stackgrowstoward

lower addresses

higheraddresses

StackPointer:%esp

IA32CallStack:Pop

Stack“Top”

Stack“Bottom”

popl Dest

12

stackgrowstoward

lower addresses

higheraddresses

StackPointer:%esp

IA32CallStack: Pop

Stack“Top”

Stack“Bottom”

popl Dest

1. Loadvaluefromaddress%esp2. Writevalue toDest3. Increment%esp by4

13

Thosebitsarestill there;we’rejustnotusingthem.

stackgrowstoward

lower addresses

higheraddresses

StackPointer:%esp

CallChainExampleyoo(…){

••who();••

}

who(…){

• • •amI();• • •amI();• • •

}

amI(…){

••amI();••

}

yoo

who

amI

amI

amI

ExampleCallChain

amI

ProcedureamI isrecursive(calls itself)

14

Base/FramePointer:%ebp

Stackframessupportprocedurecalls.Contents

LocalvariablesFunctionargumentsReturn informationTemporaryspace

ManagementSpaceallocatedwhen procedure isentered

“Set-up”codeSpacedeallocated uponreturn

“Finish”code

Whynotjustgiveeveryprocedure apermanentchunkofmemorytoholditslocalvariables, etc?

%espStackPointer

CallerFrame

Stack“Top”

15

Frameforcurrent

procedure

Example

yoo(…){

••who();••

}

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

16

who(…){

• • •amI();• • •amI();• • •

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

17

amI(…){

••amI();••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

18

amI(…){

••amI();••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

amI

19

amI(…){

••amI();••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

amI

amI

20

amI(…){

••amI();••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

amI

21

amI(…){

••amI();••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

22

who(…){

• • •amI();• • •amI();• • •

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

23

amI(…){

•••••

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

amI

24

who(…){

• • •amI();• • •amI();• • •

}

Example

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

who

25

Example

yoo(…){

••who();••

}

yoo

who

amI

amI

amI

amI

yoo

%ebp

%esp

Stack

26Howdidwerememberwheretopoint%ebp whenreturning?

ProcedureControlFlowInstructions

Procedurecall:call label1. Pushreturnaddress onstack2. Jumptolabel

Returnaddress: Address ofinstructionaftercall.Example:804854e: e8 3d 06 00 00 call 8048b90 <main>

8048553: 50 pushl %eax

Procedurereturn:ret1. Popreturn address fromstack2. Jumptoaddress

27

%esp

%eip 0x804854e

ProcedureCall/Return:1

0x108

0x10c

0x110

123

0x108

804854e: e8 3d 06 00 00 call 8048b90 <main>8048553: 50 pushl %eax

28

call 8048b90

%eip = instructionpointer=programcounter

%esp

%eip

%esp

%eip 0x804854e

0x108

0x108

0x10c

0x110

0x104

0x804854e

123

ProcedureCall/Return:2

0x108

0x10c

0x110

123

0x108

call 8048b90

804854e: e8 3d 06 00 00 call 8048b90 <main>8048553: 50 pushl %eax

0x8048553

0x104

%eip = instructionpointer=programcounter29

0x8048553

%esp

%eip

%esp

%eip 0x8048553

0x108

0x108

0x10c

0x110

0x104

0x804854e

0x8048553

123

ProcedureCall/Return:3

0x108

0x10c

0x110

123

0x108

call 8048b90

804854e: e8 3d 06 00 00 call 8048b90 <main>8048553: 50 pushl %eax

0x8048b90

0x104

%eip: programcounter30

+ 0x000063d

PC-relativeaddress

%esp

%eip

0x104

%esp

%eip 0x80485910x8048591

0x1040x104

0x108

0x10c

0x110

0x8048553

123

ProcedureCall/Return:4

0x108

0x10c

0x110

123

8048591: c3 ret

0x8048553

%eip: programcounter31

ret

0x8048553

0x108

IA32/LinuxStackFrame

33

ReturnAddress

SavedRegisters+

Local Variables

Argumentsfornextcall

Caller'sbasepointer

Argumentstocallee

CallerFrame

Base/Frame pointer%ebpStackpointer%esp

StackRegisters

CalleeFrame

Revisitingswap

int zip1 = 02481;int zip2 = 98195;

void call_swap() {swap(&zip1, &zip2);

}

void swap(int *xp, int *yp) {int t0 = *xp;int t1 = *yp;*xp = t1;*yp = t0;

}

call_swap:• • •pushl $zip2 # Global Varpushl $zip1 # Global Varcall swap• • •

&zip2

&zip1

Rtn adr %esp

ResultingStack•

••

Callingswap fromcall_swap

34

Revisitingswap

void swap(int *xp, int *yp) {int t0 = *xp;int t1 = *yp;*xp = t1;*yp = t0;

}

swap:pushl %ebpmovl %esp,%ebppushl %ebx

movl 12(%ebp),%ecxmovl 8(%ebp),%edxmovl (%ecx),%eaxmovl (%edx),%ebxmovl %eax,(%edx)movl %ebx,(%ecx)

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

Body

SetUp

Finish

35

swap Setup#1

swap:pushl %ebpmovl %esp,%ebppushl %ebx

ResultingStack

&zip2

&zip1

Rtn adr

EnteringStack

•••

36

SetUp

call_sw

apfram

e

yp

xp

Rtn adr

Old%ebp

•••

%esp%ebp

%esp%ebp

swap Setup#2

swap:pushl %ebpmovl %esp,%ebppushl %ebx

&zip2

&zip1

Rtn adr

EnteringStack

•••

yp

xp

Rtn adr

Old%ebp

•••

ResultingStack

37

SetUp

call_sw

apfram

e

%esp%ebp

%esp%ebp

swap Setup#3

swap:pushl %ebpmovl %esp,%ebppushl %ebx

&zip2

&zip1

Rtn adr

EnteringStack

•••

yp

xp

Rtn adr

Old%ebp

•••

ResultingStack

38

Old%ebx

SetUp

call_sw

apfram

e

%esp%ebp

%esp%ebp

12

8

4

swap Body

&zip2

&zip1

Rtn adr

%esp

EnteringStack

•••

%ebp

yp

xp

Rtn adr

Old%ebp

•••

ResultingStack

Old%ebx

movl 12(%ebp),%ecx # get ypmovl 8(%ebp),%edx # get xp. . .

Offsetrelativetonew%ebp

39

Body

call_sw

apfram

e

%esp%ebp

swap Finish#1

yp

xp

Rtn adr

Old%ebp

•••

Old%ebx

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

yp

xp

Rtn adr

Old%ebp

•••

ResultingStack

Old%ebx

40

Finish

FinishingStack

call_sw

apfram

e

%esp%ebp

%esp%ebp

swap Finish#2

yp

xp

Rtn adr

Old%ebp

•••

Old%ebx

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

yp

xp

Rtn adr

Old%ebp

•••

ResultingStack

41

Finish

FinishingStack

call_sw

apfram

e

%esp%ebp

%esp%ebp

swap Finish#3

yp

xp

Rtn adr

Old%ebp

•••

Old%ebx

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

ResultingStack

yp

xp

Rtn adr

•••

42

Finish

FinishingStack

call_sw

apfram

e

%esp%ebp

%esp%ebp

swap Finish#4

yp

xp

Rtn adr

Old%ebp

•••

Old%ebx

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

yp

xp

•••

ResultingStack

43

Finish

FinishingStack

call_sw

apfram

e

%esp%ebp

%esp%ebp

Disassembledswap080483a4 <swap>:80483a4: 55 push %ebp80483a5: 89 e5 mov %esp,%ebp80483a7: 53 push %ebx80483a8: 8b 55 08 mov 0x8(%ebp),%edx80483ab: 8b 4d 0c mov 0xc(%ebp),%ecx80483ae: 8b 1a mov (%edx),%ebx80483b0: 8b 01 mov (%ecx),%eax80483b2: 89 02 mov %eax,(%edx)80483b4: 89 19 mov %ebx,(%ecx)80483b6: 5b pop %ebx80483b7: c9 leave 80483b8: c3 ret

8048409: e8 96 ff ff ff call 80483a4 <swap>804840e: 8b 45 f8 mov 0xfffffff8(%ebp),%eax

CallingCode

44

mov %ebp,%esppop %ebp

relativeaddress(little endian)

swap Finish#4

yp

xp

Rtn adr

Old%ebp

•••

Old%ebx

movl -4(%ebp),%ebxmovl %ebp,%esppopl %ebpret

yp

xp

•••

ResultingStack

45

Finish

FinishingStack

call_sw

apfram

e

ObservationSaved&restored register%ebxbutnot%eax,%ecx,or%edx

%esp%ebp

%esp%ebp

RegisterSavingConventionsWhenprocedureyoo callswho:

yoo isthecallerwho isthecallee

Willregistercontentsstillbethereafteraprocedurecall?yoo:

• • •movl $12345, %edxcall whoaddl %edx, %eax• • •ret

who:• • •movl 8(%ebp), %edxaddl $98195, %edx• • •ret

47

?

RegisterSavingConventionsWhenprocedureyoo callswho:

yoo isthecallerwho isthecallee

Willregistercontentsstillbethereafteraprocedurecall?Conventions

CallerSaveCaller saves temporaryvalues initsframebeforecalling

Callee SaveCallee saves temporaryvalues initsframe beforeusing

48

IA32/LinuxRegisterSavingConventions%eax, %edx, %ecx

Caller saves priortocallif needsvaluesaftercall

%eaxalsousedtoreturnintegervalue

%ebx, %esi, %ediCallee saves ifwilluse

%esp, %ebpspecialformofcallee saverestored tooriginalvaluesbefore returning

%eax

%edx

%ecx

%ebx

%esi

%edi

%esp

%ebp

Caller-SaveTemporaries

Callee-SaveTemporaries

Special

49

APuzzle

*p = d;return x - c;

movsbl 12(%ebp),%edxmovl 16(%ebp),%eaxmovl %edx,(%eax)movswl 8(%ebp),%eaxmovl 20(%ebp),%edxsubl %eax,%edxmovl %edx,%eax

WritetheCfunctionheader,types,andorderofparameters.

Cfunctionbody:

assembly:

movsbl =movesign-extendingabytetoalong(4-byte)movswl =movesign-extendingaword(2-byte)toalong(4-byte)

Example:PointerstoLocalVariables

51

void s_helper(int x, int *accum) {if (x <= 1) {

return;} else {

int z = *accum * x;*accum = z;s_helper (x-1,accum);

}}

int sfact(int x) {int val = 1;s_helper(x, &val);return val;

}

Top-LevelCall RecursiveProcedure

Passpointertoupdatelocation

sfact(3) val =1s_helper(3,&val) val =3s_helper(2,&val) val =6s_helper(1,&val) val =6.

Temp.Space

%esp

Creating&Initializing Pointer

52

int sfact(int x) {int val = 1;s_helper(x, &val);return val;

}

_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1

Initialpartofsfact

x

Rtn adr

Old%ebp0

4

8

-4 val = 1

Unused-12

-8

-16

_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1

_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1

_sfact:pushl %ebp # Save %ebpmovl %esp,%ebp # Set %ebpsubl $16,%esp # Add 16 bytes movl 8(%ebp),%edx # edx = xmovl $1,-4(%ebp) # val = 1

%esp

%esp%ebp

Muststoreval inmemory(stack);registersdonothaveaddresses.

PassingPointer

53

int sfact(int x) {int val = 1;s_helper(x, &val);return val;

}

leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish

Callings_helper fromsfact

x

Rtn adr

Old%ebp %ebp0

4

8

val = 1-4

Unused-12

-8

-16 %esp

x

&val

Stackattime ofcall:

leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish

leal -4(%ebp),%eax # Compute &valpushl %eax # Push on stackpushl %edx # Push xcall s_helper # callmovl -4(%ebp),%eax # Return val• • • # Finish

val=x!

Muststoreval inmemory(stack);registersdonothaveaddresses.

IA32/Linux ProcedureSummarycall, ret, push, pop

Stackdisciplinefitsprocedurecall/return.*IfPcallsQ,Qreturns beforeP,includingrecursion.

Conventionssupportarbitraryfunctioncalls.Safelystoreper-call values inlocalstackframeandcallee-saved registersPushfunctionarguments attopofstackbefore callResult returned in%eax

*Take251tolearnabout languageswhereitdoesn't.

ReturnAddr

SavedRegisters

+Local

Variables

ArgumentBuild

Old%ebp

Arguments

CallerFrame

%ebp

%esp

54