; ; CPE 221 Assembly Example ; 3/6/18 ; This program multiplies two numbers by repeated addition. ; First, take absolute values of both numbers, do multiplication, ; then adjust result as necessary. AREA MULTIPLY_BY_ADDING_SUBFRAME, CODE, READONLY ENTRY LDR r1, num1 ; Put num1 in r1. LDR r2, num2 ; Put num2 in r2. LDR r3, num3 ; Put num3 in r3. LDR r4, num4 ; Put num4 in r4 ; We are now set up to test positive times positive, positive times negative, ; negative times positive and negative times negative by calling multiply ; four times MOV r11, sp ; Copy the stack pointer to the frame pointer SUB sp, sp, #12 ; Make room for two inputs and one output STR r1, [r11, #-4] ; Put num1 on the stack (position relative to frame pointer) STR r2, [r11, #-8] ; Put num2 on the stack (position relative to frame pointer) BL mpy_ne ; Branch to multiply routine and store return in lr LDR r5, [r11, #-12] ; Result is now available on the stack STR r5, case1 ; Store the result MOV sp, r11 ; Collapse the frame by moving the stack pointer final B final mpy_ne PUSH {lr} ; Push lr onto the stack so can branch and link again PUSH {r0, r1, r3, r4, r5} ; Save register contents because multiply is putting ; new values in these registers LDR r0, [r11, #-8] ; Copy the first parameter from the stack into r0 LDR r1, [r11, #-4] ; Copy the second parameter from the stack into r1 MOV r3, #0 ; Set r3 to 0, it will hold the result. TEQ r0, #0 ; Compare first parameter to 0 BEQ done ; If first parameter is 0 we are done, result = 0. TEQ r1, #0 ; Compare second parameter to 0 BEQ done ; If second parameter is 0, we are done, result = 0. PUSH {r11} ; Save old frame pointer in preparation for branching MOV r11, sp ; Copy stack pointer into the frame pointer SUB sp, sp, #8 ; Make space on the stack for one input, one output STR r1, [r11, #-4] ; Store the input parameter on the stack BL abs ; Branch to abs routine and store return in lr LDR r4, [r11, #-8] ; Copy result from the stack into r4 MOV sp, r11 ; Collapse the frame by moving the stack pointer POP {r11} ; Pull the old frame pointer off the stack PUSH {r11} ; Save old frame pointer in preparation for branching MOV r11, sp ; Copy stack pointer into the frame pointer SUB sp, sp, #8 ; Make space on the stack for one input, one output STR r0, [r11, #-4] ; Store the input parameter on the stack BL abs ; Branch to abs routine and store return in lr LDR r5, [r11, #-8] ; Copy result from the stack into r5 MOV sp, r11 ; Collapse the frame by moving the stack pointer POP {r11} ; Pull the old frame pointer off the stack adding ADD r3, r3, r5 ; Add num2. SUBS r4, r4, #1 ; Decrement r4, the abs of num1. BEQ adjust ; If r4 = 0, done adding, go to adjust. B adding ; Otherwise, need to add again. adjust MOVS r0, r0 ; Done adding, now adjust sign of result. RSBMI r3, r3, #0 ; If num2 negative, negate result. MOVS r1, r1 RSBMI r3, r3, #0 ; If num1 negative, negate result. done STR r3, [r11, #-12] ; Store result on stack for return POP {r0, r1, r3, r4, r5} ; Restore registers to their entry values POP {pc} ; Pull the saved lr value off stack and put in pc to return abs PUSH {lr} ; Push lr value in case you branch again PUSH {r0} ; Make a copy of r0, so you can use it now LDR r0, [r11, #-4] ; Copy the input parameter off of the stack CMP r0, #0 ; Test input parameter BPL d_abs ; If zero or greater, we're done RSB r0, r0, #0 ; If negative, make it positive d_abs STR r0, [r11, #-8] ; Store the result on the stack POP {r0} ; Restore register to its entry value POP {pc} ; Pull the saved lr value off stack and put in pc to return num1 DCD 8 ; Give num1 a value num2 DCD 9 ; Give num2 a value num3 DCD -8 ; Give num3 a value num4 DCD -9 ; Give num4 a value case1 SPACE 4 ; Make space for positive times positive case case2 SPACE 4 ; Make space for positive times negative case case3 SPACE 4 ; Make space for negative times positive case case4 SPACE 4 ; Make space for negative times negative case END