AND R3, R3, #0 ; Initialize step count to 0
ADD R4, R7, #0
LOOP ; Loop until X becomes 1
ADD R0, R0, #-1 ; Checks if X = 1
BRnz QUIT
ADD R0, R0, #1 ; Restores value of X
ADD R2, R0, #0 ; Copy X into R2
AND R2, R2, #1 ; Check if X is odd
BRz EVEN ; Branch to EVEN if X is even
JSR MUL3ADD1 ; Run the MUL3ADD1 subroutine if odd
ADD R0, R1, #0 ; Copy the result into X
ADD R3, R3, #1 ; Increment the step count
BRnzp LOOP ; Loop again
EVEN
JSR DIVIDEBY2 ; Run the DIVIDEBY2 subroutine if even
ADD R0, R1, #0 ; Copy the result into X
ADD R3, R3, #1 ; Increment the step count
BRnzp LOOP ; Loop again
QUIT
ADD R7, R4, #0 ; resets R7 value
RET
I need the loop to terminate at quit by returning to the user when R0 = 1, but it doesn't stop. MUL3ADD1 and DIVIDEBY2 work independently so it's not a problem with those.
Yes, the problem is that the return address is being overwritten. It is stored in R7
, and wiped out / repurposed by JSR
.
As a result RET
will retun to within its self instead of the caller.
So, that code needs to manage R7. Save it upon entry and restore it just prior to ret
. Should ba able to find examples doing that.
The registers do not stack themselves, they are globally accessible storage locations that can only hold one value at a time.
While it is relatively efficient to pass the return address location in a register, if the function repurposes R7, and intends to later return to its caller, it will have to manage the return addresses.
It is too bad, IMHO, that LC-3 simulators do not set up a stack by default, as popular MIPS and RISC V simulators (MARS,RARS) do. That means that if you want to use the stack for such temporary storage purposes, you have to establish one yourself.
The other common approach on LC-3 is to simply use a global variable to store the old/incoming R7 value so that R7 can be repurposed and still the function can find its way back to its caller. Use of global variables for these purposes precludes recursion and reentrancy, but is still a common approach on LC-3.