Functions and the Stack 10/4/16
FunctionsandtheStack10/4/16
Overview
• Stackdatastructure,appliedtomemory
• Behavioroffunctioncalls
• Storageoffunctiondata,atIA32level
“A”Stack• Astackisabasicdatastructure• Lastin,firstoutbehavior(LIFO)• Twooperations
• Push(additemtotopofstack)• Pop(removeitemfromtopofstack)
Oldestdata
Newestdata
Push(adddataitem)
Pop(removeandreturnitem)
• Applystackdatastructuretomemory• Storelocal(automatic)variables• Maintainstateforfunctions(e.g.,wheretoreturn)
• Organizedintounitscalledframes• Oneframerepresentsalloftheinformationforonefunction.• Sometimescalledactivationrecords
“The”Stack
MemoryModel
• Stackstartsatthehighestmemoryaddresses,growsintoloweraddresses.
0x0
0xFFFFFFFF
Operatingsystem
Stack
TextData
Heap
StackFrames
• Asfunctionsgetcalled,newframesaddedtostack.
• Example:Lab4• maincallsget_values()• get_values callsread_float()• read_float callsI/Olibrary
main
0xFFFFFFFF
get_values
read_float
(I/Olibrary)
StackFrames
• Asfunctionsreturn,framesremovedfromstack.
• Example:Lab4• I/Olibraryreturnstoread_float• read_float returnstoget_values• get_values returnstomain
main
0xFFFFFFFF
get_values
read_float
(I/Olibrary)
Allofthisstackgrowing/shrinkinghappensautomatically(fromtheprogrammer’sperspective).
Whatisresponsibleforcreatingandremovingstackframes?A. Theuser
B. Thecompiler
C. Clibrarycode
D. Theoperatingsystem
E. Something/someoneelse
Insight:EVERYfunctionneedsastackframe.Creating/destroyingastackframeisa(mostly)genericprocedure.
StackFrameContents• Whatneedstobestoredinastackframe?• Alternatively:Whatmust afunctionknow/access?
• Hint:Atleast5things
main
0xFFFFFFFF
get_values
read_float
StackFrameContents
• Whatneedstobestoredinastackframe?• Alternatively:Whatmust afunctionknow?
• Localvariables• Previousstackframebaseaddress• Functionarguments• Returnvalue• Returnaddress
• Savedregisters• Spilledtemporaries
main
0xFFFFFFFF
function1
function2
LocalVariables
Iftheprogrammersays:int x = 0;
Whereshouldxbestored?(Recallbasicstackdatastructure)
Whichmemoryaddressisthat?
main
0xFFFFFFFF
function1
function2
Xgoeshere
0x????????
Howshouldwedeterminetheaddresstouseforstoringanewlocalvariable?
A. Theprogrammerspecifiesthevariablelocation.
B. TheCPUstoresthelocationofthecurrentstackframe.
C. Theoperatingsystemkeepstrackofthetopofthestack.
D. Thecompilerknows/determineswherethelocaldataforeachfunctionwillbeasitgeneratescode.
E. Theaddressisdeterminedsomeotherway.
• Compiletime(static)• Informationthatisknownbyanalyzingyourprogram• Independentofthemachineandinputs
• Runtime(dynamic)• Informationthatisn’tknownuntilprogramisrunning• Dependsonmachinecharacteristicsanduserinput
TheCompilerCan…
• Determinehowmuchspaceyouneedonthestacktostorelocalvariables.
• InsertIA32instructionsforyoutosetupthestackforfunctioncalls.• Createstackframesonfunctioncall• Restorestacktopreviousstateonfunctionreturn
• Performtypechecking,etc.
CurrentStackFrame
LocalVariables
• CompilercanallocateNbytesonthestackbysubtractingNfromthe“stackpointer”:%esp
CurrentStackFrame
esp
esp - N
Nbytes
TheCompilerCan’t…• Predictuserinput.
int main() {
int x = get_user_input();
if (x > 5) {
funcA(x);
} else {
funcB();
}
}
main
0xFFFFFFFF
funcBfuncA ???
TheCompilerCan’t…• Predictuserinput.
• Assumeafunctionwillalwaysbeatacertainaddressonthestack.
Alternative:createstackframesrelativetothecurrent(dynamic)stateofthestack.
main
0xFFFFFFFF
funcBfuncA ???
funcB
StackFrameLocation
• Whereinmemoryisthecurrentstackframe?
main
0xFFFFFFFF
function1
function2
Currenttopofstack
Currentbottomofstack
Recall:IA32Registers
%eip
Generalpurposeregisters
Currentstacktop
Currentstackframe
Instructionpointer(PC)
CF ZF SF OF Conditioncodes
%eax
%ecx
%edx
%ebx
%esi
%edi
%esp
%ebp
StackFrameLocation
• Whereinmemoryisthecurrentstackframe?
• Maintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• %esp:stackpointer• %ebp:framepointer(basepointer) main
0xFFFFFFFF
function1
function2
%esp
%ebp
StackFrameLocation
• Compilerensuresthatthisinvariantholds.• We’llseehowabitlater.
• Thisiswhyalllocalvariableswe’veseeninIA32arerelativeto%ebp or%esp!
main
0xFFFFFFFF
function1
function2
%esp
%ebp
HowwouldweimplementpushingxtothetopofthestackinIA32?A. Increment%esp
Storexat(%esp)
B. Storexat(%esp)Increment%esp
C. Decrement%espStorexat(%esp)
D. Storexat(%esp)Decrement%esp
E. Copy%esp to%ebpStorexat(%ebp) main
0xFFFFFFFF
function1
function2
Xgoeshere%esp
(Topofstack)
%ebp(Framestart)
Push&Pop
• IA32providesconvenientinstructions:• pushl src
• Movestackpointerupby4bytes subl $4, %esp• Copy‘src’tocurrenttopofstack movl src, (%esp)
• popl dst• Copycurrenttopofstackto‘dst’ movl (%esp), dst• Movestackpointerdown4bytes addl $4, %esp
• src anddst arethecontentsofanyregister
LocalVariables
• Moregenerally,wecanmakespaceonthestackforNbytesbysubtractingNfrom%esp
CurrentStackFrame
CurrentStackFrame
esp esp - NNbytes
Newvariable
LocalVariables
• Moregenerally,wecanmakespaceonthestackforNbytesbysubtractingNfrom%esp• Whenwe’redone,freethespacebyaddingNbackto%esp
CurrentStackFrame
CurrentStackFrame
esp
esp - N
Nbytes
Newvariable
StackFrameContents
• Whatneedstobestoredinastackframe?• Alternatively:Whatmust afunctionknow?
• Localvariables• Previousstackframebaseaddress• Functionarguments• Returnvalue• Returnaddress
• Savedregisters• Spilledtemporaries
main
0xFFFFFFFF
function1
function2
StackFrameRelationships
• Iffunction1callsfunction2:• function1isthecaller• function2isthecallee
• Withrespecttomain:• mainisthecaller• function1isthecallee
main
0xFFFFFFFF
function1(caller)
function2(callee)
Whereshouldwestoreallthisstuff?
A. InregistersB. OntheheapC. Inthecaller’sstackframeD. Inthecallee’s stackframeE. Somewhereelse
PreviousstackframebaseaddressFunctionargumentsReturnvalueReturnaddress
CallingConvention
• Youcouldstorethisstuffwhereveryouwant!• ThehardwaredoesNOTcare.• Whatmatters:everyoneagreesonwheretofindthenecessarydata.
• Callingconvention:agreeduponsystemforexchangingdatabetweencallerandcallee
IA32CallingConvention(gcc)
• Inregister%eax:• Thereturnvalue
• Inthecallee’s stackframe:• Thecaller’s%ebp value(previousframepointer)
• Inthecaller’sframe(sharedwithcallee):• Functionarguments• Returnaddress(savedPCvalue)
IA32CallingConvention(gcc)
• Inregister%eax:• Thereturnvalue
• Inthecallee’s stackframe:• Thecaller’s%ebp value(previousframepointer)
• Inthecaller’sframe(sharedwithcallee):• Functionarguments• Returnaddress(savedPCvalue)
IA32CallingConvention(gcc)
• Inregister%eax:• Thereturnvalue
• Inthecallee’s stackframe:• Thecaller’s%ebp value(previousframepointer)
• Inthecaller’sframe(sharedwithcallee):• Functionarguments• Returnaddress(savedPCvalue)
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Mustadjust%esp,%ebp oncall/return.
caller
%esp
%ebp …
callee
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Immediatelyuponcallingafunction:1. pushl %ebp
caller
%esp
…%ebp
caller’s%ebp value
callee
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Immediatelyuponcallingafunction:1. pushl %ebp2. Set%ebp =%esp
caller
%esp
…%ebp
caller’s%ebp value
callee
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Immediatelyuponcallingafunction:1. pushl %ebp2. Set%ebp =%esp3. SubtractNfrom%esp
caller
%esp
…%ebp
caller’s%ebp value
Callee cannowexecute.
callee
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Toreturn,reversethis:
caller
%esp
…%ebp
caller’s%ebp value
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Toreturn,reversethis:1. set%esp =%ebp
caller
%esp
…%ebp
caller’s%ebp value
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Toreturn,reversethis:1. set%esp =%ebp2. popl %ebp
caller
%esp
…%ebp
caller’s%ebp value
FramePointer
• Mustmaintaininvariant:• Thecurrentfunction’sstackframeisalwaysbetweentheaddressesstoredin%esp and%ebp
• Toreturn,reversethis:1. set%esp =%ebp2. popl %ebp
caller
%esp
…%ebpBacktowherewestarted.
IA32hasanotherconvenienceinstructionforthis:leave
Recall:AssemblyWhileLoop
some_function:pushl %ebpmovl %esp, %ebp
# Your code here
movl $10, %eaxleaveret
Setupthestackframeforthisfunction.
Storereturnvaluein%eax.
Restorecaller’s%esp,%ebp.
Lab4:swap.s
swap:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
# Your code here
leave
ret
IA32CallingConvention(gcc)
• Inregister%eax:• Thereturnvalue
• Inthecallee’s stackframe:• Thecaller’s%ebp value(previousframepointer)
• Inthecaller’sframe(sharedwithcallee):• Functionarguments• Returnaddress(savedPCvalue)
FunctionArguments
• Argumentsarepushedontothestackbeforethecallinstructionjumpsintothecallee.
callee
caller
…
caller’s%ebp valueCallee arguments
InstructionsinMemory
0x0
0xFFFFFFFF
Operatingsystem
Stack
TextData
Heap
funcA:…call funcB…
funcB:pushl %ebpmovl %esp, %ebp…
FunctionA
FunctionB
…
ProgramCounter
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
TextMemoryRegionRecall:PCstorestheaddressofthenextinstruction.(Apointertothenextinstruction.)
Whatdowedonow?
FollowPC,fetchinstruction:
addl $5, %ecx
ProgramCounter
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
TextMemoryRegionRecall:PCstorestheaddressofthenextinstruction.(Apointertothenextinstruction.)
Whatdowedonow?
FollowPC,fetchinstruction:
addl $5, %ecx
UpdatePCtonextinstruction.
Executetheaddl.
ProgramCounter
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Recall:PCstorestheaddressofthenextinstruction.(Apointertothenextinstruction.)
Whatdowedonow?
FollowPC,fetchinstruction:
movl $ecx, -4(%ebp)
TextMemoryRegion
ProgramCounter
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Recall:PCstorestheaddressofthenextinstruction.(Apointertothenextinstruction.)
Whatdowedonow?
FollowPC,fetchinstruction:
movl $ecx, -4(%ebp)
UpdatePCtonextinstruction.
Executethemovl.
TextMemoryRegion
ProgramCounter
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Recall:PCstorestheaddressofthenextinstruction.(Apointertothenextinstruction.)
Whatdowedonow?
Keepexecutinginastraightlinedownwardslikethisuntil:
Wehitajumpinstruction.Wecallafunction.
TextMemoryRegion
ChangingthePC:Jump
• Onajump:• Checkconditioncodes• SetPCtoexecuteelsewhere(notnextinstruction)
• Doweeverneedtogobacktotheinstructionafterthejump?
Maybe(andifso,we’dhavealabeltojumpbackto),butusuallynot.
ChangingthePC:Functions
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Whatwe’dlikethistodo:
TextMemoryRegion
ChangingthePC:Functions
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Whatwe’dlikethistodo:
SetupfunctionB’sstack.
TextMemoryRegion
ChangingthePC:Functions
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Whatwe’dlikethistodo:
SetupfunctionB’sstack.
ExecutethebodyofB,produceresult(storedin%eax).
TextMemoryRegion
ChangingthePC:Functions
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Whatwe’dlikethistodo:
SetupfunctionB’sstack.
ExecutethebodyofB,produceresult(storedin%eax).
RestorefunctionA’sstack.
TextMemoryRegion
ChangingthePC:Functions
ProgramCounter(PC)
funcA:addl $5, %ecxmovl %ecx, -4(%ebp)…call funcBaddl %eax, %ecx…
funcB:pushl %ebpmovl %esp, %ebp…movl $10, %eaxleaveret
Whatwe’dlikethistodo:
Return:GobacktowhatweweredoingbeforefuncB started.
Unlikejumping,weintendtogoback!
TextMemoryRegion