EE 3170 Microcontroller Applications Lecture 12: Advanced Assembly Language Programming Part II- Stacks Calling Conventions & Base Pointer Usage & Subroutine Examples - Miller 5.5-5.7 Based on slides for ECE3170 by Profs. Davis, Kieckhafer, Tan, and Cischke Lecture Overview Call & Return Call PC generation Addressing Modes Return PC Storage Stack obedience w/in subroutine Return PC retrieval Subroutine Calling Conventions (1) Register (2) Memory (3) Stack EE3170/CC/Lecture#12-Part II 1 EE3170/CC/Lecture#12 - Part II 2 Ideal? Extensible? Protocol (1) Return Address Let s design our own calling convention Let s add features one at a time Already Defined by 68HC11 Architecture JSR& BSR instr. - Push PC onto stack (1) Pass Return Address (parent child) (2) Save Parent s Original Register Contents (3) Pass Call Parameters (parent child) (4) Pass Return variables (child parent) (5) Store Child s Local Variables RTN instr. - Pops PC from stack Parent: No responsibilities AND Let s make it Recursion-Friendly Allow only register-based & stack-based data passing Child: Must restore SP to original values before RTN EE3170/CC/Lecture#12 - Part II 3 EE3170/CC/Lecture#12 - Part II 4
(2) Saving Parent s Register Values Options: Parent can do it for those values it needs preserved pre-call: push needed regs post-ret: pop the pushed regs Child can do it for those registers it needs to use entry: push any registers it will use exit: pop the pushed regs 68HC11 has few registers it s not too critical We Choose: Let the child do it (3) Two Ways to Pass Call Parameters 1) Call-by-Value = pass a copy of the parameter value to subroutine Simple method - the main puts the data to be passed to the subroutine in the microprocessor registers. Can only pass 6 bytes and must take care to not to incorrectly overwrite data Subroutine cannot change the main programs data value example: ldaa param1 *content of memory w/ address param1 will be loaded to A psha 2) Call-by-Reference = pass the address of the parameter to the subroutine subroutine works on the actual variable (address of the parameter) example: ldy #param1 *address of memory labeled by param1 will be loaded to index register y pshy EE3170/CC/Lecture#12 - Part II 5 EE3170/CC/Lecture#12 - Part II 6 (3) Passing Call Parameters Stack Contents Parent must make values of parameters available Call-by-value Load in a Register Push onto the Stack Call-by-reference Interface Spec. for a given subroutine must specify: number of parameters, locations, the order in which they are stored (pushed) Author of each individual subr. makes these decisions Author of the parent must know what they are Pre-call: parent pushes call Call: JSR pushes Ret Addr Result: Ret Addr is at top are under Ret Addr Complication: Subroutine will need the before the Ret Addr EE3170/CC/Lecture#12 - Part II 7 EE3170/CC/Lecture#12 - Part II 8
Stack Frames Stack is starting to get a little complicated Several items may be pushed & popped for one subr. Pure canonical stack access is getting inconvenient Stack Frame = The set of all data needed on the stack for one routine One frame is created by call & destroyed by return Each routine has its own stack frame (incl. Main) Contents & structure are defined by call convention Frame-based Stack Access Rules Only the top frame on the stack is accessible Within the top stack frame, allowed random access Stack Frames Each routine has one Stack Frames A routine can access only its own frame The frame for the current routine is always on top Routine is allowed random access within its own frame Frame is destroyed when routine ends EE3170/CC/Lecture#12 - Part II 9 EE3170/CC/Lecture#12 - Part II 10 Accessing Parameters Accessing Parameters SP points to 1st word above top of stack Could we access parameters as offsets from SP? Theoretically, yes But, there are two problems with that: 68HC11 ISA does not support offset addressing from SP Most languages allow dynamic data structures, the SP can move unpredictably during child execution Solution: use another reg. as a Base-Pointer (BP) set it to point to a fixed location in the stack frame address parameters as offsets from the BP register Which Register to use as the BP Options = X or Y Both have offset addressing modes We choose: BP = X X instructions are smaller & faster than Y instructions Entry Protocol: push X (since child is going to use it as a BP) copy SP to X (so X points at stack frame) use indexed addressing (on X) to access parameters EE3170/CC/Lecture#12 - Part II 11 EE3170/CC/Lecture#12 - Part II 12
Implementing BP Protocol Protocol Development In entry protocol of subroutine psh? * push other regs * to be used by child Can now access by indexed addressing on X Exit protocol of subroutine must undo the pushes (in reverse order) push stack-passed load reg-passed Post-Return (parent) instr(s) to remove stack-passed psh? * push other regs pul? * pop other regs EE3170/CC/Lecture#12 - Part II 13 EE3170/CC/Lecture#12 - Part II 14 Example: Protocol Example Assume parent passes 2 single-byte parameters in the stack, 1 parameter in accumulator B Assume child routine will need to use: accumulator A accumulator B - but only to read the parameter value in B doesn t need to be pushed ldab param1 ldab param2 ldab param3 jsr child Post-Return (parent) psha? * push other regs pula? * pop other regs EE3170/CC/Lecture#12 - Part II 15 EE3170/CC/Lecture#12 - Part II 16
(4) Passing Return Variables Protocol Development If Passed in Stack parent must leave room in stack frame for child to store them often can over-write the call parameters IF need extra space for more return variables THEN parent can reserve that space with des instr. des = decrement stack pointer equivalent to push nothing Child stores return vars with indexed addressing on X Parent can pop them off stack after return push stack-passed leave extra space for return variables load reg-passed Post-Return (parent) pop return variables instr(s) to remove stack-passed psh? * push other regs pul? * pop other regs EE3170/CC/Lecture#12 - Part II 17 EE3170/CC/Lecture#12 - Part II 18 Protocol Example (5) Subroutine Local Variables ldab param1 ldab param2 des des ldab param3 jsr child Post-Return (parent) Pop return variables psha? * push other regs pula * pop other regs Could declare storage space with the routine e.g. using rmb directives Works, but has disadvantages Only works with non-recursive subroutines recursive call would over-write at the same addresses Only works for static variables need to know how many there are at assembly time Requires direct or extended addressing NOT lead to position-independent code Reserved storage is permanent Can be used for simple routines with few variables EE3170/CC/Lecture#12 - Part II 19 EE3170/CC/Lecture#12 - Part II 20
(5) Subroutine Local Variables Protocol Summary Can also store local variables on the stack can access in stack-order can also access randomly via indexing on X Need to allocate space in stack frame for local vars leave a hole in frame just before pushing X so variables will have positive offsets from X recall indexed addressing always has positive offsets Implementation: There is no convenient instr. to subtract from the SP Miller suggests sequence of des instructions Arbitrary Parameters/Returns Supported by using Stack for Parameters/Returns Support Recursion Store local variables also on Stack Random access to stack-based parameters/variables Use Base Pointer (X) to access stack variables Convention typical of those used in compilers Highly Extensible calling convention Flexibility is prioritized over speed for large software packages Reading Assignment: Miller 5.5-5.7 (examples) EE3170/CC/Lecture#12 - Part II 21 EE3170/CC/Lecture#12 - Part II 22