+1 (315) 557-6473 

Convert Assembly Code from Arm Mode to Thumb Mode Assignment Solution.


Instructions

Objective
Write a program to Convert assembly code from Arm mode to thumb mode.

Requirements and Specifications

Description:
Purpose:
The purpose of this lab is to provide students experience with the ARM Thumb mode with assembly programming.
Directions:
Students are to take the previously submitted ARM labs (Lab 1 and Lab 2) and convert them to run under ARM Thumb. No other changes to the code are to be made OTHER to have the existing code to assemble and run correctly under Thumb mode. Each lab is to have the same functionality as required by the grading rubick.
How to get into ARM Thumb mode:
After the label for main insert the following code:
ldr r0, =startthumb + 1
bx r0
.code 16 @Make all this code thumb mode. Will not exit back out.
startthumb:
There is no need to return back to 32-bit mode so the code needed to convert back to non-thumb mode is not needed. See the textbook section 4.6.1 for the differences between the ARM and ARM Thumb versions of the code.
Note:
  1. The UMULL instruction will NOT work on the Pi Zeros. It works just fine on the Pi 4s. Here are your choices:
  2. 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.
  3. 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.
Screenshots of output
Convert assembly code from Arm mode to thumb mode Convert assembly code from Arm mode to thumb mode 1 Convert assembly code from Arm mode to thumb mode 2

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"