Sei sulla pagina 1di 15

Stack Mechanics & Motivation

† Stack Motivation/Limitations of static variables


EE 3170 Microcontroller „
„
Subroutines / multiple call-site procedures
Recursion
Applications „ Interrupt Service Routines

Lecture 12: Advanced Assembly Language Programming † Stacks


Part I: Stacks and Subroutines „ Definition of the stack data structure
- Miller §5.4 - § 5.5
„ Stack management and the SP Register
„ 68HC11 stack management instructions
Based on slides for ECE3170 by Profs. Davis, Kieckhafer, Tan, and Cischke
„ 68HC11 stack example

EE3170/CC/Lecture#12-Part I 1 EE3170/CC/Lecture#12 - Part I 2

Stacks Motivation 1: Subroutines


† Stacks perform a necessary function of a † It is desirable to have a subroutine which can
computer be invoked from multiple call-sites

† They are not the ONLY method, but they are the † This implies that each call-site must
„ have a common protocol for passing parameters
most common method
„ store live variables at the time of the subroutine
invocation
† Briefly discuss 3 motivations before mechanics to „ have a common protocol for returning values from
subroutine
help motivate the understanding
† A Stack (and associated usage protocol) is a
† Break from thinking about linear execution common method to accomplish these
towards depth-first tree-shaped execution model requirements
EE3170/CC/Lecture#12 - Part I 3 EE3170/CC/Lecture#12 - Part I 4

1
Motivation 2: Recursion Motivation 3: Interrupt Service Routines (ISR)
† Recursion – a subroutine which calls itself † Interrupts (we will learn about them later) enable
code (service routine) to be invoked by an outside
† A variable “n” may have multiple instances at signal (i.e. service keyboard interrupt)
any point in time
† Similar problem to that of Subroutines – but
† Fibonacci (example) programmer does not determine call-site
„ fib( n ) = if ( n = 0 ) then 0
if ( n = 1 ) then 1
else fib( n-1 ) + fib( n-2 ) † Because programmer can not constrain call-site,
all registers used in a ISR must be saved at the
† Multiple instances implies that static variable beginning of an ISR and loaded/restored at the
addresses are not sufficient end of an ISR

EE3170/CC/Lecture#12 - Part I 5 EE3170/CC/Lecture#12 - Part I 6

Stacks Stack Operation & Management (added)


† Stack
„ A Dynamic Data Structure † To emulate the behavior of a stack. All needed is
† The stack is a temporary storage place „ Some unused memory + index register, called stack pointer
„ Access is strictly Last-In-First-Out (LIFO) † always points to the next available (empty) location above the
current top of the stack.
„ Structure:

† A stack can be implemented without special hardware


„ 68HC11 has a special double-byte stack pointer register SP
„ and special purpose instructions for controlling it.

† The only other thing needed to implement a stack is


decide where the bottom of the stack is
„ initialize the stack pointer to this value when the stack is empty.

EE3170/CC/Lecture#12 - Part I 7 EE3170/CC/Lecture#12 - Part I 8

2
Stack Operation & Management (added) Stacks
† Stack grows from higher addresses to lower † Stack Access Operations
„ the top of the stack grows upwards
„ Note: the text shows memory upside-down in its stack
„ Push – Put new item on top of the stack
examples so that the stack grows downward „ Pop – Remove the top item from stack
† The bottom of the stack is often located at the highest
available memory address. † Microprocessor Interpretation
„ Stack is a contiguous set of memory
† The stack allows dynamic memory allocation
„ don’t have to decide when you write the program: how many
„ Push – Copy data from a register into the next
bytes to reserve, just push stuff on when you need to save it. available word above current top
† New word becomes new top of stack
† Push too much without popping „ Pop – Move data from top word in stack into a register
„ you can overwrite your program! It’s your responsibility not to † Next word down in the stack becomes new top
do this.
† Value of previous top is lost to the stack

EE3170/CC/Lecture#12 - Part I 9 EE3170/CC/Lecture#12 - Part I 10

Stack Management Stack Management


† Address of the top of the stack changes with each Push † Stack Location in Memory (initial value of SP)
or Pop
† Stack Size grows and shrinks as the program runs
† Need an addressing register to keep track of the „ Push increase stack size
„ Pop decrease stack size
address of the top of the stack
† Want to keep stack from running into program memory space as it
† Stack Pointer (SP) register grows
„ Register holding address of the first empty byte above the top
of stack † Code & mem space starts at lowest address (00..00) and grows
„ The last register not-yet-discussed in the 68HC11 programming into higher addresses
model
† Therefore, we start stacks at highest address (FF..FF) and let it
† SP must be incremented or decremented with each grow into lower addresses
Push or Pop
„ This is done automatically by the hardware. † Stack grows down (textbook)/up

EE3170/CC/Lecture#12 - Part I 11 EE3170/CC/Lecture#12 - Part I 12

3
Stack Management Stack Management
† Result: code and stack to not “collide” † Stack Operations
„ until there is no memory space left „ Push
† Put data on stack
„ known as stack overflow † Decrement SP (after)
„ overflow occurs with infinite recursion † PUSH Reg
MEM[SP] = Reg
PC
SP = SP-1

„ Pull
† Remove data from stack
† Increment SP (before)
† POP Reg
SP SP = SP+1
Reg= MEM[SP]

EE3170/CC/Lecture#12 - Part I 13 EE3170/CC/Lecture#12 - Part I 14

68HC11 Stack Management 68HC11 Stack Management


† Double-Precision Push & Pull instructions
† In 68HC11:
„ PSHX & PSHY
„ Pops are called Pull † store lo-byte of X (or Y) & decrement SP
„ ISA predates the standardization of the term † store hi-byte of X (or Y) & decrement SP
Pop
„ PULX & PULY
† increment SP & load hi-byte of X (or Y)
† Single-Precision Push & Pull instructions † increment SP & load lo-byte of X (or Y)
„ PSHA & PSHB
† Store A (or B) onto stack & decrement SP † There is no PSHD or PULD
„ D = A:B
„ PULA & PULB
„ Can emulate PSHD with PSHB and PSHA
† Increment SP & Load A (or B) from stack

EE3170/CC/Lecture#12 - Part I 15 EE3170/CC/Lecture#12 - Part I 16

4
68HC11 Stack Management Stack Example
ORG $E100
† Stack Pointer Manipulation Instructions * INITIALIZE STACK
„ LDS & STS START LDS #$B7FF • SP
† Load and Store SP * CREATE SAMPLE DATA B7FC • • •
† needed to initialize SP LDAA #$22 B7FD • A
LDAB #$33 B7FE • •
„ INS & DES * STORE DATA IN STACK B7FF • B
† Increment and Decrement SP PSHA • •
† NOT needed during normal PSHx & PULx instructions PSHB
* GET DATA FROM STACK
„ TSX, TXS, TSY, TYS PULA
† Transfer (copy) between SP and X or Y regs PULB
SWI

EE3170/CC/Lecture#12 - Part I 17 EE3170/CC/Lecture#12 - Part I 18

Stack Example Stack Example


ORG $E100 ORG $E100
* INITIALIZE STACK * INITIALIZE STACK
START LDS #$B7FF • SP START LDS #$B7FF • SP
* CREATE SAMPLE DATA * CREATE SAMPLE DATA
B7FC • B7 FF B7FC • B7 FF
LDAA #$22 LDAA #$22
B7FD • A B7FD • A
LDAB #$33 LDAB #$33
B7FE • • B7FE • 22
* STORE DATA IN STACK * STORE DATA IN STACK
B7FF • B B7FF • B
PSHA PSHA
• • • 33
PSHB PSHB
* GET DATA FROM STACK * GET DATA FROM STACK
PULA PULA
PULB PULB
SWI SWI

EE3170/CC/Lecture#12 - Part I 19 EE3170/CC/Lecture#12 - Part I 20

5
Stack Example Stack Example
ORG $E100 ORG $E100
* INITIALIZE STACK * INITIALIZE STACK
• SP
START LDS #$B7FF • SP START LDS #$B7FF
* CREATE SAMPLE DATA B7FC • B7 FD
B7FC • B7 FE * CREATE SAMPLE DATA
LDAA #$22 B7FD • A
B7FD • A LDAA #$22
LDAB #$33 B7FE 33 22
B7FE • 22 LDAB #$33
* STORE DATA IN STACK * STORE DATA IN STACK B7FF 22 B
B7FF 22 B
PSHA • 33
• 33 PSHA
PSHB PSHB
* GET DATA FROM STACK * GET DATA FROM STACK
PULA PULA
PULB PULB
SWI SWI

EE3170/CC/Lecture#12 - Part I 21 EE3170/CC/Lecture#12 - Part I 22

Stack Example Stack Example


ORG $E100 ORG $E100
* INITIALIZE STACK * INITIALIZE STACK
START LDS #$B7FF • SP START LDS #$B7FF • SP
* CREATE SAMPLE DATA * CREATE SAMPLE DATA
B7FC • B7 FE B7FC • B7 FF
LDAA #$22 LDAA #$22
B7FD • A B7FD • A
LDAB #$33 LDAB #$33
B7FE 33 33 B7FE 33 33
* STORE DATA IN STACK * STORE DATA IN STACK
B7FF 22 B B7FF 22 B
PSHA PSHA
• 33 • 22
PSHB PSHB
* GET DATA FROM STACK * GET DATA FROM STACK
PULA PULA
PULB PULB
SWI SWI

EE3170/CC/Lecture#12 - Part I 23 EE3170/CC/Lecture#12 - Part I 24

6
Stack Instructions What is a Subroutine?
† LDS † PSHX, PSHY † Subroutine (a.k.a. Procedure or Function) =
„ Load SP „ Push index register on
„ Creates a stack stack (2 bytes) † A reusable program module
„ Write it once
† PSHA, PSHB † PULX, PULY
„ Store it once
„ Push accumulator on „ Pull from stack to index „ invoke it from several places in the main program
stack register (2 bytes) „ when finished it returns to the main program
„ Decrement SP (after) † TSX, TXS, TSY, TYS
† PULA, PULB „ Transfer the SP to index † A sequence of instructions invoked so that it
register looks like a single instruction in the main
„ Pull from stack to source-code
accumulator „ Transfer index register
to SP „ e.g. “call” label-of-first-instruction-in-subroutine
„ Increment SP (before)

EE3170/CC/Lecture#12 - Part I 25 EE3170/CC/Lecture#12 - Part I 26

Subroutines How to use subroutines? (added)


† To use a subroutine
† A program module used multiple times during the „ there must be a mechanism for transferring control (as in a
branch) to the beginning of the subroutine and
execution of a program „ then returning to execute what would have been the next
instruction (the return address) after the subroutine is done.
„ This should work no matter where in memory the subroutine is
† It can be imbedded repeatedly in the main called from.
program listing BUT is more efficiently CALLED „ It should also work even if the subroutine is called from inside
by the main program. another subroutine.

† It turns out that the stack is the perfect mechanism for


keeping track of the return address.
† Subroutines increase our programming
productivity † It is also very helpful in passing parameters to and from
subroutines and in defining variables local to subroutines

EE3170/CC/Lecture#12 - Part I 27 EE3170/CC/Lecture#12 - Part I 28

7
Subroutines Desirable Properties
† It is desirable to have a subroutine which can be
invoked from multiple call-sites † Independence
„ Subr. & main program may be written independently
† Subr makes no references to addresses or labels defined in
† This implies that each call-site must the main
„ have a common protocol for passing parameters † and vice-versa (except for the first instruction)
„ store live variables at the time of the subroutine
invocation
„ have a common protocol for returning values from † Subr. & main can be edited without affecting
subroutine each other
† A Stack (and associated usage protocol) is a
common method to accomplish these † Subr & main can be assembled independently
requirements and linked at loading time
EE3170/CC/Lecture#12 - Part I 29 EE3170/CC/Lecture#12 - Part I 30

Good Subroutines (added) Call and Return


† Are correctly structured † Calling A Subroutine
„ Single entry point and a single exit point „ main program “transfers control” to the subroutine
„ First instruction is always the first instruction executed „ main program “jumps” to subroutine
„ Ends with RTS „ PC = address of (first instr in subroutine)

† Take extra care when using microprocessor


resources within the subroutine † Returning From a Subroutine
„ Very easy for the main program and subroutine to conflict „ subr. transfers control back to the main program
when both use a particular accumulator or register „ subr. “jumps” back into main program
„ PC = address of (first instruction after the Calling
instr)

EE3170/CC/Lecture#12 - Part I 31 EE3170/CC/Lecture#12 - Part I 32

8
Call and Return Subroutine Definitions
† Subr. can be called from many locations in main
† Always returns to the instr. immediately after the call † Nesting – One subroutine calls another
subroutine

† Nesting Level – Number of calls needed to


reach a routine
„ Level 0 – Main program
„ Level 1 – Subroutine called by main program
„ Level 2 – Subroutine called by a Level 1 routine
„ Level k – Subroutine called by a Level k-1 routine

EE3170/CC/Lecture#12 - Part I 33 EE3170/CC/Lecture#12 - Part I 34

Subroutine Definitions Subroutine Linkage


† Parent – The routine executing the call instruction (caller) † Subroutine Linkage = the process of:
† Child – the called routine (callee) „ Passing parameters and return values between parent
and child
† Return Address – Address of instruction in parent program to which the „ Saving and restoring the return address
child returns
„ Just after the call instruction
„ PC incremented during fetch of call † Calling Convention = protocol to implement
† Parameters – Data passed from parent to child linkage
„ Defines actions to be taken on call and return
† Return Values – Data passed from child to parent „ Assigns responsibilities to parent and child
† Recursion – When a subroutine calls itself „ Must be strictly obeyed, OR ELSE:
„ Subroutine is its own parent and child † data could get lost or corrupted
„ Example, factorial N! = N x (N-1)! † return address could get lost or corrupted

EE3170/CC/Lecture#12 - Part I 35 EE3170/CC/Lecture#12 - Part I 36

9
Return Address Linkage 68HC11 Call Instructions
† Where do we store the return address?
„ Do not want to use a register † Two “Call” Instructions
† inhibits nesting and recursion „ BSR addr = Branch to subroutine starting at “addr”
„ Do not want to use a “fixed” static memory location † relative addressing (short range)
† inhibits nesting and recursion „ JSR addr = Jump to subroutine starting at “addr”
† subr. would have to know a parent’s label † direct, extended, or indexed addressing

† It is temporary † Actions:
„ only needed until return
„ Push current PC onto stack ( = return address)
„ would like to “liberate” that word when done
„ PC = “addr” (actually the calculated effective address)

† Stacks are designed to perform these functions

EE3170/CC/Lecture#12 - Part I 37 EE3170/CC/Lecture#12 - Part I 38

68HC11 Return Instruction


† One “return” Instruction
„ RTS = Return from Subroutine

† Actions:
„ Pop stack to PC ( = return address)
† PC = previously pushed return address
† next instruction fetched will be instruction after the Call

„ Caution:
† The subr. could use the stack while running
† must be careful to pop everything it pushes
† then return address is at “top” for RTS instruction

EE3170/CC/Lecture#12 - Part I 39 EE3170/CC/Lecture#12 - Part I 40

10
Subroutine Return Instructions Subroutine Example (added)
† The only condoned way of † Every subroutine should
returning from a be documented with a
subroutine is
† to retrieve the return
brief “header”
address from the stack „ sets it off visually,

† The stack can always be „ gives its name, its inputs


modified by a child and outputs, its basic
procedure function, and

† If the child does not wish


to modify the return „ its side effects (i.e., any
address, it should perform registers it modifies or
an equal # of Push & Pop other important effects it
has that may not be part of
its obvious function).

EE3170/CC/Lecture#12 - Part I 41 EE3170/CC/Lecture#12 - Part I 42

Parent-Child Communication Details & Attention


† Values to be Passed † During Call and the Return sequence
„ we do not have to use PSHx or PULx instructions
„ Return Address (parent → child) „ we do not explicitly adjust the stack pointer
„ Call Parameters (parent → child) „ all of that is built-into the BSR, JSR, and RTS instr.
† Note: in some processors it is not built-in
„ Return Variables (child → parent)
† Attention
„ Subroutine could use the stack while running.
† Values to be Preserved „ Subroutine must be careful to pop everything it
„ Parent’s Original Register Contents pushes.
† “Take only pictures, leave only footprints.”
„ Parent’s Local Variables † Make sure the stack is the same as when the subroutine
was called.
„ Child’s Local Variables „ We need the return address to be at the top of the
stack for rts instruction
EE3170/CC/Lecture#12 - Part I 43 EE3170/CC/Lecture#12 - Part I 44

11
3 Types of Calling Conventions Register-Based Calling
† Types are based on how data is † Parent
passed between parent and child „ Stores parameters in registers
„ 1. Register-based: passes data in registers „ Calls child
„ 2. Memory-based: passes data in a fixed
memory area † Child
† usually uses mem space immediately following „ Uses parameters stored in registers
the call „ Stores return values in registers
† management gets a little tricky „ Returns to parent
„ 3. Stack-based: passes data in the stack
† everybody knows where it is (SP tells them) † Parent
† expands and shrinks with demand „ Uses return values in registers

EE3170/CC/Lecture#12 - Part I 45 EE3170/CC/Lecture#12 - Part I 46

Register-Based Calling Conventions Register-Based Calling Conventions


† Parent † Child
† Example: Summation of (j = 1 to N)
„ sum(n) { … adds clra * sum = 0
for (s=0, j=1 ; j <= n ; j++) {s += j} ldab #N tstb *set CCs w/ B
return s; } jsr adds loop beq retn * while b<>0
† Storage Convention … aba *sum = sum + i
„ A = return value s
decb *i = i-1
„ B = calling parameter n
bra loop
† For simplicity:
retn rts
„ We will ignore the likely overflow problem in B
EE3170/CC/Lecture#12 - Part I 47 EE3170/CC/Lecture#12 - Part I 48

12
Register-Based Calling Conventions Memory-Based Calling Conventions
† Parent
† Advantages „ Store parameters in Data Link Area in memory
„ Very fast (no extra load or store) † Usually the memory words right after the call
„ Pretty easy too. „ Call child

† Disadvantages † Child
„ May have more parameters than available registers „ get return address from the stack
† Given that we have a whopping 4 registers in the HC11, this is
extremely likely. „ access parameters using offset from return address
„ Nested Calls „ Store any return values using offset
† Require more registers „ Return to parent
† Must coordinate register usage between subroutines
„ Recursion † Parent
† Child wants same registers as parent
„ Load return values from Data Link Area
† Parent must move parameters before calling child

EE3170/CC/Lecture#12 - Part I 49 EE3170/CC/Lecture#12 - Part I 50

Memory-Based Calling Conventions Memory-Based Calling Conventions


† Parent † Advantages
„ …
ldab #N „ Arbitrary number of parameters
stab LNK
jsr adds „ Some older ISAs do this efficiently
LNK rmb 1 *Reserve Memory Bytes
ldaa LNK

† Disadvantages
† Child
„ adds pulx *get base for LNK „ Slower (more loads and stores)
inx *correct ret addr „ Requires mixing of instructions and data in memory
pshx *restore ret addr
clra *sum = 0 (BAD!!)
ldab -1,X *get val of N
loop beq retn *while b != 0 „ Complex
aba *sum = sum + i † jsr does not actually store the return address
decb *i = i-1
bra loop † Subroutine must adjust and re-push the return address
retn staa -1,X *save sum † Very easy to mess this one up
rts

EE3170/CC/Lecture#12 - Part I 51 EE3170/CC/Lecture#12 - Part I 52

13
Stack-Based Calling Conventions Stack-Based Calling Convention
† Parent † Parent
„ Pushes parameters onto stack „ …
ldab #N
„ Calls child pshb
† No address passing - address is in SP jsr adds
pula
† Child …
„ Pops return address to safe place ‰ Child

„
† Usually the X or Y register
Pops parameters off stack
ƒ adds pulx * save RA
clra * sum = 0
pulb * get N
„ Pushes return values on stack loop beq return * while b != 0
„ Re-pushes return address on stack aba * sum = sum + i
decb
„ Returns to parent bra loop
return psha * save sum
† Parent pshx * push RA
„ Pops returned values off stack rts

EE3170/CC/Lecture#12 - Part I 53 EE3170/CC/Lecture#12 - Part I 54

Stack-Based Calling Conventions Comments on Calling


† Advantages † Register-based conventions are fastest and
„ Arbitrary number of parameters
simplest.
„ No need to know storage location at assembly time
„ Nested Calls † However, stack-based are preferred.
† Each routine builds on previous stack „ Flexible and predictable
† Each routine has its storage space
„ Recursion † We have avoided a few complexities so far
† Same as any other nested call „ What if:
† Parent has data stored in a register
† Child wants to use that register
† Disadvantages
„ Nesting and recursion are complex.
„ Slower - still have to load and store

EE3170/CC/Lecture#12 - Part I 55 EE3170/CC/Lecture#12 - Part I 56

14
Summary of Stacks & Subroutines
† The stack is a dynamic data structure mostly maintained
by the hardware.
† You need to initialize the stack pretty much all the time.
† Pushing puts data on the top of the stack.
† Pulling takes data off the top of the stack.
† Subroutines are called by jsr or bsr and returned from by
rts.
† Three different calling conventions:
„ Register-based
„ Memory-based
„ Stack-based

EE3170/CC/Lecture#12 - Part I 57

15

Potrebbero piacerti anche