; 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