Subroutine and Stack
| Type | Quiz 3 Material |
|---|
Subroutine is another name for function
There is no “function” abstraction in LC-3 assembly. Need to create our own abstraction

JSR(Jump to Subroutine)
The JSR instruction computes the target address of the subroutine by sign-extending the 11-bit offset (bits [10:0]) of the instruction to 16 bits and adding that to the incremented PC.

Saves the PC value into R7 and then sets PC to the target1.
R7 = PC*(incremented)
PC = PC* + PCOffset11
PC-offset addressing (usually called with a label)
Note the order is important; we need to save the PC before changing it
JSRR(Jump to Subroutine, Register)
Same as JSR, but uses a register for the subroutine's address instead of a label/offset
R7 = PC*
PC = SR
RET(Return)
A special case of JMP. Equivalent to JMP R7
PC = R7
This is actually a “pseudo-instruction” since it assembles to the exact same bits as JMP R7
The Stack
- The stack is a location in memory that is useful for storing temporary program data
- Subroutine calls –parameters, return values
- Local variables –what if our 8 registers aren’t enough
Grows “downwards” towards smaller memory addresses from a fixed starting location
LAST IN FIRST OUT




How to call a subroutine
- Push Argument in reverse order
- JSR
After subroutine returns
- Pop return value(on the stack)
Frame Pointer


Calling Conventions
A caller is a function that calls another function; a callee is a function that was called. The currently-executing function is a callee, but not a caller.
Good read on caller/calleee: https://cs61.seas.harvard.edu/site/2018/Asm2/



If you only have one variable, subroutine will always be the same
If there are two or more, need to allocate more space
Building up the stack



Subroutine calling a subroutine


Questions
- What is the stack? What is it used for?
- What do the values in R5, R6, and R7 represent in the LC-3?
R5 - frame pointer
R6 - stack pointer
R7 - return address
- What is a "frame pointer"? Why do we need it?
Points to the first local variable on the stack. Exists to directly reference everything under it (stack frame up to that point is constant and never different. Everything after the frame pointer is dynamic and cant literally point to anything consistently.
- How do you push a value onto the stack?

DO NOT HAVE TO INITIALIZE R6
- How do you pop a value off of the stack?

- What if stack is already full/empty?
- Before pushing, test overflow
- Before popping, text underflow
- Stack points to heap —> Stack Overflow




;subroutine template(2 args)
subroutine
ADD R6, R6, -4
STR R7, R6, 2
STR R5, R6, 1
ADD R5, R6, 0
ADD R6, R6, -5
STR R0, R5, -1
STR R1, R5, -2
STR R2, R5, -3
STR R3, R5, -4
STR R4, R5, -5
;perform subroutine operation here
;recursive call to subroutine.
ADD R6, R6, -1 ; Push 1 on the stack
STR RX, R6, 0 ; RX is the first arg to push
ADD R6, R6, -1 ;Push 1 on the stack
STR RX, R6, 0 ;RX is the second arg to push
JSR subroutine ;Call subroutine
LDR RX, R6, 0 ;Store return value to RX
ADD R6, R6, 3 ;Pop the two pushed and the return value
STR RX, R5, 0 ;Store return value to local variable in current stack
TEARDOWN
LDR R0, R5, 0 ;R0 = Local variable that holds the return value
STR R0, R5, 3 ;Retval = R0
LDR R4, R5, -5 ; Restore R4
LDR R3, R5, -4 ; Restore R3
LDR R2, R5, -3 ; Restore R2
LDR R1, R5, -2 ; Restore R0
LDR R0, R5, -1 ; Restore R1
ADD R6, R5, 0 ; Restore SP
LDR R5, R6, 1 ; Restore FP
LDR R7, R6, 2 ; Restore RA
ADD R6, R6, 3 ; Pop ra,fp,lv1
RET


