130 likes | 227 Views
Computer Science 210 Computer Organization. Recursive Subroutines System Stack Management. Iteration vs Recursion. def factorial(n): product = 1 while n > 0: product *= n n -= 1 return product. def factorial(n): if n == 0: return 1 else:
E N D
Computer Science 210Computer Organization Recursive Subroutines System Stack Management
Iteration vs Recursion def factorial(n): product = 1 while n > 0: product *= n n -= 1 return product def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) Including 0 in the domain makes the assembler version easier
; Main program code LD R1, NUMBER JSR FACT ST R2, NUMBER HALT ; Main program data variables NUMBER .BLKW 1 ;; Subroutine FACT ; Returns the factorial of R1 in R2 ; Input parameter: R1 (the number) ; Output parameter: R2 (the product) ; R3 = temporary working storage ;; Pseudocode: ; product = 1 ; while number > 0 ; product *= number ; number -= 1 FACTST R7, FACTTEMPR7 ; Save my return address ST R3, FACTTEMPR3 ; Save the working storage ST R1, FACTTEMPR1 ; Save my input parameter LD R2, FACTONE ; Initialize the product to 1 WHILEJSR MUL ; R3 = R1 * R2 ADD R2, R3, #0 ; Shift the product back to R2 ADD R1, R1, #-1 ; Decrement the number BRp WHILE LD R1, FACTTEMPR1 ; Restore my input parameter LD R3, FACTTEMPR3 ; Restore the working storage LD R7, FACTTEMPR7 ; Restore my return address RET ; Data for subroutine FACT FACTONE .FILL 1 FACTTEMPR1 .BLKW 1 FACTTEMPR3 .BLKW 1 FACTTEMPR7 .BLKW 1 Iterative factorial routine in assembler
; Main program code LD R1, NUMBER JSR FACT ST R2, NUMBER HALT ; Main program data variables NUMBER .BLKW 1 ;; Subroutine FACT ; Returns the factorial of R1 in R2 ; Input parameter: R1 ; Output parameter: R2 ; R3 = temporary working storage ;; Pseudocode: ; if number == 0 ; return 1 ; else ; return number * fact(number – 1) FACT ADD R1, R1, #0 ; If number > 0 then recurse BRp RECURSE LD R2, FACTONE ; Base case: return 1 RET RECURSEST R7, FACTTEMPR7 ; Save my return address ST R3, FACTTEMPR3 ; Save the working storage ST R1, FACTTEMPR1 ; Save my input parameter ADD R1, R1, #-1 ; Decrement the number JSR FACT LD R1, FACTTEMPR1 ; Restore my input parameter JSR MUL ; R3 = R1 * R2 [number * fact(number – 1)] ADD R2, R3, #0 ; Shift the product back to R2 LD R3, FACTTEMPR3 ; Restore the working storage LD R7, FACTTEMPR7 ; Restore my return address RET ; Data for subroutine FACT FACTONE .FILL 1 FACTTEMPR1 .BLKW 1 FACTTEMPR3 .BLKW 1 FACTTEMPR7 .BLKW 1 Recursive factorial routine in assembler
Problem • Each call of the subroutine overwrites R7 with its return address, but all of the calls save R7 in the same data variable • Each call must return to a context in which its own parameter R1 was saved, but they’re all saved in the same data variable • Restoration of registers for more than one recursive call is impossible
Solution • We need a means of stacking up saved values so the contexts of calls can be saved and restored in a last in, first out manner (many instances of R1, R7, etc.) • A system stack provides for this
The Stack Interface • The stack structure consists of a stack pointer (in R6, which now can’t be used for anything else) and two subroutines, PUSH and POP • At program startup, the stack pointer is initialized to an address just above the keyboard status register • R0 provides the interface for data pushed or popped
The Stack Implementation • The stack pointer moves up (to a smaller memory address) during a PUSH • The stack pointer moves down (to a larger memory address) during a POP • Won’t bother with stack overflow or underflow for now
The Place of the Runtime Stack in Memory System .ORIG: x0000 System memory Main program .ORIG: x3000 Main program (code and data) Subroutines (code and data) Runtime System Each push decrements the stack pointer by one Stack grows upwards toward user memory STACK BOTTOM: xFDFF Device registers
Defining the Stack Resource ; Main program code LD R6, STACKBOTTOM ; Initialize the stack pointer LD R1, NUMBER JSR FACT ST R2, NUMBER HALT ; Main program data variables STACKBOTTOM .FILL xFDFF; Address of the bottom of the stack NUMBER .BLKW 1 ;; Subroutine PUSH ; Copies R0 to the top of the stack and decrements the stack pointer ; Input parameters: R0 (the datum) and R6 (the stack pointer) ; Output parameter: R6 (the stack pointer) PUSH ADD R6, R6, #-1 STR R0, R6, #0 RET ;; Subroutine POP ; Copies the top of the stack to R0 and increments the stack pointer ; Input parameter: R6 (the stack pointer) ; Output parameters: R0 (the datum) R6 (the stack pointer) POP LDR R0, R6, #0 ADD R6, R6, #1 RET
Recursive factorial routine in assembler ;; Subroutine FACT ; Returns the factorial of R1 in R2 ; Input parameter: R1 ; Output parameter: R2 ; R3 = temporary working storage ;; Pseudocode: ; if number == 0 ; return 1 ; else ; return number * fact(number – 1) FACT ADD R1, R1, #0 ; If number > 0 then recurse BRp RECURSE LD R2, FACTONE ; Base case: return 1 RET RECURSEADD R0, R7, #0 ; Save my return address JSR PUSH ADD R0, R3, #0 ; Save the working storage JSR PUSH ADD R0, R1, #0 ; Save my input parameter JSR PUSH ADD R1, R1, #-1 ; Decrement the number JSR FACT JSRPOP ; Restore my input parameter ADD R1, R0, #0 JSR MUL ; R3 = R1 * R2 [number * fact(number – 1)] ADD R2, R3, #0 ; Shift the product back to R2 JSRPOP ; Restore the working storage ADD R3, R0, #0 JSRPOP ; Restore my return address ADD R7, R0, #0 RET ; Data for subroutine FACT FACTONE .FILL 1
Using the Stack • The stack can eliminate the need for declaring subroutine data variables in many cases • For example, any routine that calls another one must save and restore R7 • Stack ‘em up!
Costs and Benefits • Using a stack incurs the cost of extra subroutine calls for PUSH and POP • A large chunk of memory might go to waste • Subroutines in early languages like FORTRAN, with no recursion, could be completely static (no extra overhead for subroutine calls)