Instructions
Requirements and Specifications
- The UMULL instruction will NOT work on the Pi Zeros. It works just fine on the Pi 4s. Here are your choices:
- Leave the UMULL in your code because when the TA runs it they will be using a Pi 4. Just make sure you are only using registers r0 - r7 in the instruction. There is a drawback in that you will not be able to test your code 100% before you submit it.
- Leave the UMULL as is but change back to .code 32 to execute the UMULL then switch back to the .code 16 after executing the instruction. Least preferred option.



Source Code
Lab 1
/*File: JulietAwoyale_Lab1.s*/
/*Author Juliet Awoyale*/
/*Purpose Using ARM Auto-Indexing to access array elements & to do*/
/*nested subroutine calls*/
.text
.align 2
.global printArray
.global main
.syntax unified
.arm
.fpu vfp
.type main, %function
.type printArray, %function
main:
ldr r0, =startthumb + 1
bx r0
.code 16 @Make all this code thumb mode. Will not exit back out.
startthumb:
/*save context*/
push {r4, r5, r6, r7, lr}
/*pass first welcome msg*/
ldr r0, =.welcome1
/*call puts*/
bl puts
/*pass second welcome msg*/
ldr r0, =.welcome2
/*call puts*/
bl puts
/*r2 now points to array1*/
ldr r2, =array1
/*r3 is the index*/
mov r3, #0
/*store array1 base to be used in third for*/
mov r6, r2
.firstFor:
//Array1[i] = i + 2;
/*store r1 (r3 + 2) in r2[r3]*/
add r1, r3, #2
str r1, [r2]
add r2, #4
/*R3 ++ */
add r3, #1
cmp r3, #10
bne .firstFor
/*prepare second array for initialization*/
ldr r5, =array2
/* r4 is the index */
mov r4, #0
/*store array2 base to be used in third for*/
mov r7, r5
.secondFor:
/*r1 is a temp variable to get input from user*/
sub sp, sp, #4
mov r1, sp
ldr r0, =.scanfParam
bl __isoc99_scanf
/*get returned value in r3*/
pop {r3}
/* store array2[r4] = r3*/
str r3, [r5]
add r5, #4
/*r4++*/
add r4, r4, #1
cmp r4, #10
bne .secondFor
/* r1 has array3 base addr*/
ldr r1, =array3
/* r3 is the index*/
mov r3, #0
.thirdFor:
/*get array1[r3]*/
ldr r0, [r6]
add r6, #4
/*get array2[r3]*/
ldr r2, [r7]
add r7, #4
/*r2 = array1[r3] * array2[r3]*/
mul r2, r2, r0
/*store r2 in array3[r3]*/
str r2, [r1]
add r1, #4
/*r3++*/
add r3, r3, #1
cmp r3, #10
bne .thirdFor
/*pass array1 to printarray*/
ldr r0, =array1
bl printArray
/*pass array2 to printarray*/
ldr r0, =array2
bl printArray
/*pass array3 to printarray*/
ldr r0, =array3
bl printArray
/*return 0 to os*/
mov r0, #0
/*restore saved context*/
pop {r4, r5, r6, r7, pc}
printArray:
/*save caller context */
push {r4, r5, r6, lr}
/*r5 points to array base*/
mov r5, r0
/* pass printfparam */
ldr r6, =.printfParam
mov r4, #0
.forLoop:
/* get arr[r5] and update */
ldr r1, [r5]
add r5, #4
mov r0, r6
bl printf
add r4, r4, #1
cmp r4, #10
bne .forLoop
//pass '\n' to putchar
mov r0, #10
bl putchar
pop {r4, r5, r6, pc}
.L16:
.align 2
.data
.membank:
.word .welcome1
.word .welcome2
.word array1
.word array2
.word array3
.word .scanfParam
.comm array3,40,4
.comm array2,40,4
.comm array1,40,4
.section .rodata
.printfParam:
.ascii "%d\011\000"
.welcome1:
.ascii "Welcome! please enter 10 digits to store it in arra"
.ascii "y2\000"
.welcome2:
.ascii "Array 1 elements are stored with the respective ind"
.ascii "ex * 2\000"
.scanfParam:
.ascii "%d\000"
Lab 2
/*Filename awoyale.s*/
/*Author Juliet Awoyale*/
/*Purpose Using the stack to pass parameters to and from their own defined*/
/*subroutines/functions in ARM assembly*/
.text
.align 2
.global printArray
.global main
.syntax unified
.arm
.fpu vfp
.type main, %function
.type addition, %function
.type subtraction, %function
.type multiplication, %function
.type division, %function
main:
ldr r0, =startthumb + 1
bx r0
.code 16 @Make all this code thumb mode. Will not exit back out.
startthumb:
/*save context*/
push {r4, r5, r6, lr}
/* print welcome message */
ldr r0, =welcome
bl printf
startLoop:
/* print a newline */
mov r0, #10
bl putchar
readFirstVal:
/* prompt for first value */
ldr r0, =prompt1
bl printf
/* read result in temp variable in stack */
sub sp, sp, #4
mov r1, sp
ldr r0, =num_format
bl scanf
/*get returned value in r4*/
pop {r4}
1: bl getchar /* remove \n */
cmp r0, #10
bne 1b
cmp r4, #0 /* verify it's not negative */
bge readSecondVal /* if positive, continue */
/* print error message */
ldr r0, =negativeError
bl printf
b readFirstVal /* repeat loop */
readSecondVal:
/* prompt for second value */
ldr r0, =prompt2
bl printf
/* read result in temp variable in stack */
sub sp, sp, #4
mov r1, sp
ldr r0, =num_format
bl scanf
1: bl getchar /* remove \n */
cmp r0, #10
bne 1b
/*get returned value in r5*/
pop {r5}
cmp r5, #0 /* verify it's not negative */
bge readOperator /* if positive, continue */
/* print error message */
ldr r0, =negativeError
bl printf
b readSecondVal /* repeat loop */
readOperator:
/* prompt for operator */
ldr r0, =prompt3
bl printf
/* read operator */
bl getchar
mov r6, r0
bl getchar /* remove \n */
cmp r6, #'+' /* verify it's valid operator */
beq makeAdd /* if +, make add */
cmp r6, #'-' /* verify it's valid operator */
beq makeSub /* if -, make sub */
cmp r6, #'*' /* verify it's valid operator */
beq makeMul /* if *, make mul */
cmp r6, #'/' /* verify it's valid operator */
beq makeDiv /* if +, make div */
/* print error message */
ldr r0, =operatorError
bl printf
b readOperator /* repeat loop */
makeAdd:
push {r4, r5} /* pass first and second number and operand as arguments */
bl addition /* call function to make addition */
pop {r3, r6} /* pop result in r3, overflow in r6 */
cmp r6, #0 /* check if there was overflow */
beq printAdd /* if not, print result */
/* print overflow message */
ldr r0, =overflowError
bl printf
b askRepeat /* ask user if we must repeat */
printAdd:
/* print result message and value */
ldr r0, =addResultMsg
mov r1, r4
mov r2, r5
bl printf
b askRepeat /* ask user if we must repeat */
makeSub:
push {r4, r5} /* pass first and second number and operand as arguments */
bl subtraction /* call function to make subtraction */
pop {r3} /* pop result in r3 */
/* print result message and value */
ldr r0, =subResultMsg
mov r1, r4
mov r2, r5
bl printf
b askRepeat /* ask user if we must repeat */
makeMul:
push {r4, r5} /* pass first and second number and operand as arguments */
bl multiplication /* call function to make multiplication */
pop {r3, r6} /* pop result in r3, overflow in r6 */
cmp r6, #0 /* check if there was overflow */
beq printMul /* if not, print result */
/* print overflow message */
ldr r0, =overflowError
bl printf
b askRepeat /* ask user if we must repeat */
printMul:
/* print result message and value */
ldr r0, =mulResultMsg
mov r1, r4
mov r2, r5
bl printf
b askRepeat /* ask user if we must repeat */
makeDiv:
cmp r5, #0 /* check division by zero */
bne callDiv /* if not zero, make division */
/* print error message */
ldr r0, =divZeroError
bl printf
b askRepeat /* ask if another operation must be done */
callDiv:
push {r4, r5} /* pass first and second number and operand as arguments */
bl division /* call function to make division */
pop {r3, r6} /* pop quotient in r1 and remainder in r6*/
/* print result message and values */
ldr r0, =divResultMsg
mov r1, r4
mov r2, r5
push {r6}
bl printf
add sp, sp, #4 /*pop last argument*/
askRepeat:
/* prompt for new calculation */
ldr r0, =repeatMsg
bl printf
/* read operator */
bl getchar
mov r6, r0
bl getchar /* remove \n */
cmp r6, #'y' /* if user selected y*/
beq repLoop /* read first value again */
cmp r6, #'Y' /* if user selected Y */
bne exitProg /* if not, exit program */
repLoop:
b startLoop
exitProg:
/*return 0 to os*/
mov r0, #0
/*restore saved context*/
pop {r4, r5, r6, pc}
/* Addition function, receives 2 operand arguments in stack, returns
the result and overflow on top of stack */
addition:
pop {r0, r2} /* pop arguments */
mov r1, #0 /* clear overflow */
adds r0, r2 /* make operation */
bvc addEnd /* if no overflow, end */
mov r1, #1 /*else, set overflow*/
addEnd:
push {r0, r1} /* push result and overflow */
mov pc, lr /* return */
/* Subtraction function, receives 2 operand arguments in stack, returns
the result on top of stack */
subtraction:
pop {r0, r1} /* pop arguments */
sub r0, r0, r1 /* make operation */
push {r0} /* push result */
mov pc, lr /* return */
/* Multiplication function, receives 2 operand arguments in stack, returns
the result and overflow on top of stack */
multiplication:
pop {r0, r2} /* pop arguments */
mov r1, #0 /* clear overflow */
umull r0, r1, r0, r2 /* make operation */
cmp r0, #0
bge mulEnd /* if no overflow, end */
mov r1, #1 /*else, set overflow*/
mulEnd:
push {r0, r1} /* push result and overflow */
mov pc, lr /* return */
/* Division function, receives 2 operand arguments in stack, returns
the resultting quotient and remainder on top of stack */
division:
pop {r2, r3} /* pop arguments */
/* initialize quotient to zero */
mov r0, #0
divLoop:
/*if dividend < divisor, end */
cmp r2, r3
blt divEnd
/* use subtracted dividend in next iteration */
sub r2, r3
/* increment quotient */
add r0, r0, #1
/* repeat loop */
b divLoop
divEnd:
push {r0, r2} /* push result */
mov pc, lr /* return */
.section .rodata
welcome:
.asciz "Welcome! Enter positive integers and an operator for the simple calculator\n"
prompt1:
.asciz "Please enter first operand: "
prompt2:
.asciz "Please enter second operand: "
prompt3:
.asciz "Please enter operator (+, -, *, /): "
negativeError:
.asciz "The number must be positive or zero. Please try again.\n"
operatorError:
.asciz "The operator must be one of +, -, * or /. Please try again.\n"
repeatMsg:
.asciz "Do you want to make another calculation (y/n)?: "
addResultMsg:
.asciz "\n%d + %d = %d\n\n"
subResultMsg:
.asciz "\n%d - %d = %d\n\n"
mulResultMsg:
.asciz "\n%d * %d = %d\n\n"
divResultMsg:
.asciz "\n%d / %d, quotient = %d , remainder = %d\n\n"
divZeroError:
.asciz "\nDivision by zero is not allowed.\n\n"
overflowError:
.asciz "\nOverflow while making operation!\n\n"
num_format:
.asciz "%d"