600 likes | 751 Views
Mehmet Can Vuran, Instructor University of Nebraska-Lincoln. CSCE 230, Fall 2013 Chapter 2 Stacks and Subroutines ( § 2.6–2.7) . Acknowledgement: Overheads adapted from those provided by the authors of the textbook. Stacks.
E N D
Mehmet Can Vuran, Instructor University of Nebraska-Lincoln CSCE 230, Fall 2013Chapter 2Stacks and Subroutines (§ 2.6–2.7) Acknowledgement: Overheads adapted from those provided by the authors of the textbook
Stacks • A stack is a list of data elements whereelements are added/removed at top end only • Also known as pushdown stack orlast-in-first-out (LIFO) stack • We push a new element on the stack topor pop the top element from the stack • Programmer can create a stack in the memory • There is often a special processor stack as well
Processor Stack • Processor has stack pointer (SP) registerthat points to top of the processor stack • Push operation involves two instructions: Subtract SP, SP, #4 Store Rj, (SP) • Pop operation also involves two instructions: Load Rj, (SP) Add SP, SP, #4 • Maintenance of stack requires checking when the stack is empty or overflows – can be done by checking the SP against lower and upper bounds. • Among other things, the processor stack is useful in subroutine calls.
NIOS-II Registers Stack pointer (SP) register(should) points to top of the processor stack
Initial Stack 60 64 68 72 76 80 84 88 92 96 100 SP = 100 [something]
Add couple input parameters 60 64 68 72 76 80 84 88 92 96 100 #A SP = 92 N [something]
After register saves 60 64 68 72 76 80 84 88 92 96 100 R5 SP = 72 R4 R3 R2 R1 #A N [something]
Update stack with an output parameter 60 64 68 72 76 80 84 88 92 96 100 R5 SP = 72 R4 R3 R2 R1 #A Max Value [something]
After return from a function 60 64 68 72 76 80 84 88 92 96 100 #A SP=92 Max Value [something]
After stack restore by calling program 60 64 68 72 76 80 84 88 92 96 100 SP=100 [something]
The first rule of stack operations is… • You do not talk about… • Leave the stack as you found it * • * some exceptions apply
Main Usages of Stack • Subroutine calls • Parameter passing
Subroutine Linkage • During execution of Call instruction,PC upated to point to instruction after Call • Save this address for Return instruction to use • Simplest method: place address in link register (return address register) • Call instruction performs two operations:store updated PC contents in link register,then branch to target (subroutine) address • Return just branches to address in link register
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return 1000 PC 204 LINK
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 1000 LINK • 204
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 1000 LINK • 204
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return 2000 PC 1604 LINK 204
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 2000 LINK 1604
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC #Return+4 LINK 1604
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 1604 LINK 1604
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 1604 LINK 1604
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return PC 1604 LINK 1604
Subroutines Nesting: Example SUB1 SUB2 SUB3 • . • . • . • 200 Call SUB2 • 204 Next Instr. • . • . • . • First Instr. • . • . • Call SUB3 • Next Instr. • . • . • Return • 2000 First Instr. • . • . • . • Return ERROR! PC 1604 LINK 1604
Analysis and Solution • When nested calls are made, the last call made is first one to be returned, i.e. the call-return protocol is Last-In First-Out (LIFO). • The nested calls can be arbitrarily deep, e.g. for recursive routines. • Hence, subroutines use the processor stack to store the Link register values during nested calls.
Parameter Passing • Mechanism hidden in HLL but must be explicit in assembly language. • A program may call a subroutine many times with different data to obtain different results • Information exchange to/from a subroutineis called parameter passing • Pass input parameters before the subroutine Call receive output parameters after the call • Parameters may be passed & received in registers • Simple, but limited to available registers • Alternative: use stack for parameter passing,and also for local variables & saving registers
Example: Parameters Passed in Registers • Convert the example program of finding the max of N numbers to a subroutine: • Calling program provides N (number of elements) and the address of the first number (i.e., A[0]) • Subroutine MAX(N, #A) returns the max value of N numbers stored starting at location #A. • Hence, there are two input parameters and one output parameter. • First, consider passing& receiving parameters in registers (we use the register assignments in the code we developed earlier to keep it simple) • N in reg. R3 • Address #A of A[0] in reg. R5 • Max value returned in R1 • Assume the values of N and A[0] are at location N and A.
Sketch of Solution • Calling Program • Load parameters N and A in the designated registers (R3 & R5) • Call MAX • Return value should be available in the designated register (R1) • Subroutine (MAX) • Push registers (other than parameter registers) used by the subroutine on the stack (i.e. push R2 and R4) • Find the value of the max element and place it in R1 (code identical to what we already saw except for the last two lines, since the value is to be returned in register R1) • Pop registers from the stack (& update stack) • Return • Note: Since MAX does not call another subroutine (it is a leaf subroutine), it does not need to save the Link register on the stack.
Sketch of Solution (contd.) • Calling Program • Load parameters in designated registers Move R3, #N # Location of N Load R3, (R3) # Value of N Load R5, #A # Address of first element • Call MAX Call MAX • Max value will be available in R1 after return
Sketch of Solution (contd.) • Subroutine (MAX) • Push registers R2 and R4 used by the subroutine on the stack Subtract SP, SP, #8 # Create room for two items Store R2, 4(SP) # Push R2 Store R4, (SP) # Push R4 • Find the value of the max element <Code here from before except last two lines> • Pop registers from the stack (& update stack) LoadR2, 4(SP) # Restore R2 Load R4, (SP) # Restore R4 Add SP, SP, #8 # Update stack pointer • Return Return
Convert Max(N,A) Code to Subroutine: Original Code Assembly Code Move R3, #N Load R3, (R3) Move R5, #A Load R1, (R5) Move R2, #1 Loop:Add R5, R5, #4 Load R4, (R5) Branch_if_(R1>=R4) Skip Move R1, R4 Skip: Add R2, R2, #1 Branch_if_(R3>R2) Loop Move R2, #Max Store R1, (R2)
Convert Max(A,N) Code to Subroutine (1) • Break the Code into three pieces: • Becomes part of calling program for passing parameters • Becomes part of the subroutine; precede it with register saves; follow it with register restores and return • Becomes part of calling program to save returned value Assembly Code Move R3, #N Load R3, (R3) Move R5, #A Load R1, (R5) Move R2, #1 Loop:Add R5, R5, #4 Load R4, (R5) Branch_if_(R1>=R4) Skip Move R1, R4 Skip: Add R2, R2, #1 Branch_if_(R3>R2) Loop Move R2, #Max Store R1, (R2) 1 2 3
Convert Max(A,N) Code to Subroutine (2) MAX Subroutine Calling Program Move R3, #N Load R3, (R3) Move R5, #A Move R2, #Max Store R1, (R2) 1 • Load R1, (R5) • Move R2, #1 • Loop: Add R5, R5, #4 • Load R4, (R5) • Branch_if_(R1>=R4) Skip • Move R1, R4 • Skip: Add R2, R2, #1 • Branch_if_(R3>R2) Loop 2 3
Convert Max(A,N) Code to Subroutine (3) MAX Subroutine Calling Program Move R3, #N Load R3, (R3) Move R5, #A Move R2, #Max Store R1, (R2) MAX: <Save local variables and saving registers on stack> 1 Call MAX • Load R1, (R5) • Move R2, #1 • Loop: Add R5, R5, #4 • Load R4, (R5) • Branch_if_(R1>=R4) Skip • Move R1, R4 • Skip: Add R2, R2, #1 • Branch_if_(R3>R2) Loop 2 3 <Restore locals and saving registers on stack> Return
Convert Max(A,N) Code to Subroutine (4) MAX Subroutine MAX: Subtract SP, SP, #8 Store R2, 4(SP) Store R4, (SP) Calling Program Move R3, #N Load R3, (R3) Move R5, #A Move R2, #Max Store R1, (R2) • Load R1, (R5) • Move R2, #1 • Loop: Add R5, R5, #4 • Load R4, (R5) • Branch_if_(R1>=R4) Skip • Move R1, R4 • Skip: Add R2, R2, #1 • Branch_if_(R3>R2) Loop 1 2 Call MAX • Load R2, 4(SP) • Load R4, (SP) Add SP, SP, #8 Return 3
Exercise • Convert the code for the calling program and MAX to Nios II and verify it works as expected.
Passing Parameters on the Stack • Assume A calls B with input parameters i1, …,inand B returns resulting values o1, …, om.Assume m <= n (common case). • General Scheme: • A pushes i1, …,inon the stack and calls B. • B pushes any (saving) registers it would need for its computation on the stack; also the return-address register if it is not a leaf procedure. • B performs its computation and writes the resulting values o1, …, omon the stack (reusing the space used by input parameters). • B pops the saving registers from the stack and returns.
Passing Parameters on the Stack: Example Max(A,N) • Calling Program • Push input parameters onto stack (grows high to low), Subtract SP, SP, #8# Create room for 2 items Load R2, #N # Address of N in R2 Load R2, (R2) # Value of N in R2 Store R2, 4(SP) # Push it on the stack Load R2, #A# Get the second parameter in R2 Store R2, (SP) # push it on the stack • Call subroutine Call MAX • Get max value from the stack and restores stack (pop input parameters) Load R1,4(SP) # Result pushed on stack by MAX # Result overwrites value of N on stack Add SP, SP, #8 # Effectively pops stack
Passing Parameters on the Stack: Example Max(A,N) - (contd.) • Subroutine MAX • Save all regs. it will use (R1 – R5) on stack Subtract SP, SP, #20Create room for five items Store R1, 16(SP) Push R1 Store R2, 12(SP) Push R2 … … Store R5, (SP) Push R5 • Load input parameters from stack and compute sum Load R3, 24(SP) Get N into R3 Load R5, 20(SP) Get #A into R5 • Body of the Subroutine: <Code from before will need to change – see later how> • Restore saved registers and pop stack, return LoadR1, 16(SP) Restore R1 LoadR2, 12(SP) R2 … … Load R5, (SP) R5 Add SP, SP, #20 Pop stack Return Return to calling program
Passing Parameters on the Stack: Changes to Max(A,N) • Required Changes • Push R1–R5 on stack • R3 and R5 must be initialized from the stack • Last two lines must be replaced with pushing the result in R1 onto stack where input parameter N was passed. • Restore R1-R5 and pop stack • Return Earlier Assembly Code Move R3, #N Load R3, (R3) Move R5, #A Load R1, (R5) Move R2, #1 Loop:Add R5, R5, #4 Load R4, (R5) Branch_if_(R1>=R4) Skip Move R1, R4 Skip: Add R2, R2, #1 Branch_if_(R3>R2) Loop Move R2, #Max Store R1, (R2)
Initial Stack 60 64 68 72 76 80 84 88 92 96 100 SP = 100 [something]
Add couple parameters 60 64 68 72 76 80 84 88 92 96 100 #A SP = 92 N [something]
After register saves 60 64 68 72 76 80 84 88 92 96 100 R5 SP = 72 R4 R3 R2 R1 #A N [something]
Update stack with output parameter 60 64 68 72 76 80 84 88 92 96 100 R5 SP = 72 R4 R3 R2 R1 #A Max Value [something]
After return from a function 60 64 68 72 76 80 84 88 92 96 100 #A SP=92 Max Value [something]
After stack restore by calling program 60 64 68 72 76 80 84 88 92 96 100 SP=100 [something]
Passing Parameters on the Stack: Changes to Max(A,N) • Required Changes • Push R1–R5 on stack • MAX:Subtract SP, SP, #20 • Store R1, 16(SP) Push R1 • StoreR2, 12(SP) Push R2 • … … • Store R5, (SP) Push R5 • Move R3, #N • Load R3, (R3) • Move R5, #A • Load R1, (R5) • Move R2, #1 • Loop:Add R5, R5, #4 • Load R4, (R5) • Branch_if_(R1>=R4) Skip • Move R1, R4 • Skip: Add R2, R2, #1 • Branch_if_(R3>R2) Loop • Move R2, #Max • Store R1, (R2)
Passing Parameters on the Stack: Changes to Max(A,N) • Required Changes • Push R1–R5 on stack • R3 and R5 must be initialized from the stack • MAX: Subtract SP, SP, #20 • Store R1, 16(SP) Push R1 • StoreR2, 12(SP) Push R2 • … … • Store R5, (SP) Push R5 • Load R3, 24(SP) • Load R5, 20(SP) • Move R2, #1 • Loop:Add R5, R5, #4 • Load R4, (R5) • Branch_if_(R1>=R4) Skip • Move R1, R4 • Skip: Add R2, R2, #1 • Branch_if_(R3>R2) Loop • Move R2, #Max • Store R1, (R2)