; initialize SP to lower address so that
; it can be viewed in "Memory Contents"
MOV SP, #0x1100
MOV R0, #9 ; m=9
MOV R1, #5 ; n=5
SUB SP, SP, #8 ; get 2 cells (8 bytes) for params
STR R0, [SP, #4] ; send m, put it in "first" spot
STR R1, [SP, #0] ; send n, put it in "second" spot
BL MULTIPLY ; call a function - updates LR
LDR R2, [SP, #0] ; copy result from top of stack
ADD SP, SP, #12 ; release 3 cells (2 params + 1 result)
END ; stop overall execution
MULTIPLY
SUB SP, SP, #4 ; get 1 cell for result
STMDB SP!, {LR, R12, R0, R1, R2} ; preserve registers function plans to use
; - must use ! to change SP
; - careful with DB vs IA (Dec Before, Inc After)
ADD R12, SP, #28 ; set FP = SP + 7*4 for 8 cells (2 params, 1 return, 5 saved regs)
LDR R1, [R12, #-4] ; copy n
CMP R1, #1 ; check base case: n = 1?
BNE RECURSION
LDR R2, [R12, #0] ; copy m, result = m
STR R2, [R12, #-8] ; put result in its cell
BAL RESTORE ; restore registers, leave
RECURSION ; not done, call recursively
LDR R0, [R12, #0] ; copy m from params via FP
LDR R1, [R12, #-4] ; copy n from params via FP
SUB R1, R1, #1 ; n=n-1
SUB SP, SP, #8 ; get 2 cells for params
STR R0, [SP, #4] ; send m
STR R1, [SP, #0] ; send updated n
BL MULTIPLY ; call a function - updates LR
LDR R2, [SP, #0] ; copy result = m*(n-1)
ADD SP, SP, #12 ; release 3 cells (2 params + 1 result)
LDR R0, [R12, #0] ; copy m (though R0 already has m)
ADD R2, R2, R0 ; result += m
STR R2, [R12, #-8] ; put result in its cell
RESTORE
LDMIA SP!, {LR, R12, R0, R1, R2} ; restore registers preserved earlier
; - must use ! to change SP
; - DB become IA (opposite dir)
MOV PC, LR ; leave by setting program counter to return address