Evaluation of a Given Arithmetic Expression

Subroutines in ARM assembly assignment help

.data strMessage1: .asciz "Name: your name" strMessage2: .asciz "\nClass: CS 3B" strMessage3: .asciz "\n Lab: RASM1" strMessage4: .asciz "\nDate: 2/18/2019\n\n" strPrompt: .asciz "Enter a whole number: " strEqOpen: .asciz "(" strEqSum: .asciz " + " strEqClose1: .asciz ") - (" strEqClose2: .asciz ") = " strMessage5: .asciz "\nThe address of the 4 ints:\n" strMinus: .asciz "-" strTab: .asciz "\t" strLF: .asciz "\n" strVal: .skip 11 @ space to save a maximum of 10 ascii digits + a zero for each number numBuffer: .skip 20 @ buffer for conversions hexTable: .asciz "0123456789ABCDEF" .balign 4 A: .word 0 B: .word 0 C: .word 0 D: .word 0 X: .word 0 .text .global _start @ provide a program starting address to Linker .equ BUFSIZE,10 @ Size of input buffer .balign 4 _start: ldr r1, =strMessage1 @ Title Message1 bl putstring @ Call subroutine to print message ldr r1, =strMessage2 @ Title Message2 bl putstring @ Call subroutine to print message ldr r1, =strMessage3 @ Title Message3 bl putstring @ Call subroutine to print message ldr r1, =strMessage4 @ Title Message4 bl putstring @ Call subroutine to print message ldr r1, =strPrompt @ Message asking for input of first number bl putstring @ Call subroutine to print prompt ldr r1, =strVal @ Set point to input buffer mov r2, #BUFSIZE @ Maximum number of bytes to receive bl getstring @ Call subroutine to get keyboard input ldr r0, =strVal @ convert first number to integer bl convert ldr R1, =A @ save result in variable A str R0, [R1] ldr r1, =strPrompt @ Message asking for input of second number bl putstring @ Call subroutine to print prompt ldr r1, =strVal @ Set point to input buffer mov r2, #BUFSIZE @ Maximum number of bytes to receive bl getstring @ Call subroutine to get keyboard input ldr r0, =strVal @ convert second number to integer bl convert ldr R1, =B @ save result in variable B str R0, [R1] ldr r1, =strPrompt @ Message asking for input of third number bl putstring @ Call subroutine to print prompt ldr r1, =strVal @ Set point to input buffer mov r2, #BUFSIZE @ Maximum number of bytes to receive bl getstring @ Call subroutine to get keyboard input ldr r0, =strVal @ convert third number to integer bl convert ldr R1, =C @ save result in variable C str R0, [R1] ldr r1, =strPrompt @ Message asking for input of fourth number bl putstring @ Call subroutine to print prompt ldr r1, =strVal @ Set point to input buffer mov r2, #BUFSIZE @ Maximum number of bytes to receive bl getstring @ Call subroutine to get keyboard input ldr r0, =strVal @ convert fourth number to integer bl convert ldr R1, =D @ save result in variable D str R0, [R1] ldr r1, =strEqOpen @ Print first part of equation bl putstring @ Call subroutine to print prompt ldr r0, =A @ print value of A ldr r0, [r0] bl printInteger ldr r1, =strEqSum @ Print sum bl putstring @ Call subroutine to print prompt ldr r0, =B @ print value of B ldr r0, [r0] bl printInteger ldr r1, =strEqClose1 @ Print closing parenthesis and sum bl putstring @ Call subroutine to print prompt ldr r0, =C @ print value of C ldr r0, [r0] bl printInteger ldr r1, =strEqSum @ Print sum bl putstring @ Call subroutine to print prompt ldr r0, =D @ print value of D ldr r0, [r0] bl printInteger ldr r1, =strEqClose2 @ Print closing parenthesis and equal sign bl putstring @ Call subroutine to print prompt @ calculate equation result: ldr r0, =A ldr r0, [r0] ldr r1, =B ldr r1, [r1] ldr r2, =C ldr r2, [r2] ldr r3, =D ldr r3, [r3] add r0, r0, r1 @ (A+B) add r1, r2, r3 @ (C+D) sub r0, r0, r1 @ (A+B) - (C+D) ldr r1, =X str r0, [r1] @ save result in variable bl printInteger @ print result in screen ldr r1, =strMessage5 @ Print address message bl putstring @ Call subroutine to print prompt ldr r0, =A @ print address of A bl printHexadecimal ldr r1, =strTab @ Print tab bl putstring @ Call subroutine to print string ldr r0, =B @ print address of B bl printHexadecimal ldr r1, =strTab @ Print tab bl putstring @ Call subroutine to print string ldr r0, =C @ print address of C bl printHexadecimal ldr r1, =strTab @ Print tab bl putstring @ Call subroutine to print string ldr r0, =D @ print address of D bl printHexadecimal ldr r1, =strLF @ Print line feed bl putstring @ Call subroutine to print string mov r0, #0 @ Exit Status code set to 0 to indicate "normal completion" mov r7, #1 @ service command code (1) will terminate this program svc 0 @ Issue Linux command to terminate program @ Subroutine to divide by 10 @ R0: number to divide @ On return: @ R0: number divided by 10 @ All registers are preserved div10: push {R1-R3} @ Preserve working register contents. ldr R1, =0xCCCCCCCD @ special value used for dividing by 10 umull R2,R3,R1,R0 @ divide r0 by 10 mov R0, R3, LSR #3 @ put r0=r0/10 pop {R1-R3} @ Restore saved register contents bx LR @ Return to the calling program. @ Subroutine to convert a numeric ascii string to a integer @ R0: Points to the string to convert @ On return: @ R0: Converted number @ All registers are preserved convert: push {R1-R4} @ Preserve working register contents. mov R1, R0 @ save pointer to string in R1 mov R0, #0 @ put sign in R0, assume positive mov R4, #0 @ R4 will have converted number, init to zero ldrb R2, [R1] @ load first character from the string cmp R2, #'-' @ see if the number was negative bne startcnv @ if not, start conversion add R1, R1, #1 @ skip sign character mov R0, #1 @ put sign in R0, is negative startcnv: ldrb R2, [R1] @ load character from string cmp R2, #48 @ if it's end of string, end conversion blt endcnv sub R2, R2, #48 @ convert ascii digit to integer mov R3, #10 mul R4, R3, R4 @ multiply old number by 10 add R4, R4, R2 @ add digit add R1, R1, #1 @ advance to next character in string b startcnv endcnv: cmp R0, #0 beq retpos neg R4, R4 @ if negative, convert to negative retpos: mov R0, R4 @ return converted number pop {R1-R4} @ Restore saved register contents bx LR @ Return to the calling program. @ Subroutine to print an integer @ R0: number to print @ All registers are preserved printInteger: push {R0-R6, LR} @ Preserve working register contents. ldr R5, =numBuffer @ point to buffer to save conversion add R5, R5, #10 @ point to end of buffer mov R1, #0 @ save end of string in the conversion buffer strb R1, [R5] mov R6, #3 @ r6 will count the comma positions mov R2, R0 @ save number in R2 cmp R2, #0 @ see if the number was negative bge startp @ if not, start print neg R2, R2 @ else, convert number to positive ldr r1, =strMinus @ print minus sign bl putstring @ Call subroutine to print the string startp: mov R0, R2 @ divide number by 10 bl div10 mov R3, #10 @ calculate remainder to get digit mul R4, R0, R3 sub R4, R2, R4 add R4, R4, #48 @ convert digit to ascii add R5, R5, #-1 strb R4,[R5] @ save in buffer subs R6, R6, #1 @ decrement comma counter bne skip mov R6, #3 @ reload counter cmp R0, #0 @ see if there are still digits to print beq skip @ if not, don't put a comma mov R4, #',' add R5, R5, #-1 strb R4,[R5] @ else save comma in buffer skip: movs R2, R0 @ repeat while the number is not zero bne startp mov R1, R5 @ print resulting conversion bl putstring pop {R0-R6, LR} @ Restore saved register contents bx LR @ Return to the calling program. @ Subroutine to print an integer as a 32 bit hexadecimal @ R0: number to print @ All registers are preserved printHexadecimal: push {R0-R5, LR} @ Preserve working register contents. ldr R1, =numBuffer @ point to buffer to save conversion ldr R2, =hexTable @ point to hex conversion table with R3 ldr R3, =#28 @ number of times to shift number ploop: lsr R4, R0, R3 @ shift to the right to get next hex digit and R4, R4, #0xF @ mask to leave only 4 bits ldrb R4, [R2, R4] @ get conversion to hex using table strb R4,[R1],#1 @ save in buffer subs R3, R3, #4 @ decrement number of times to shift bge ploop @ repeat while the shift is not negative ldr R0, =#0 strb R0,[R1] @ save end of string char ldr R1, =numBuffer @ print resulting conversion bl putstring pop {R0-R5, LR} @ Restore saved register contents bx LR @ Return to the calling program. .end @ Subroutine Provided a pointer to a space to sa ve a null terminated @ string, and a number of byutes to read, it will read a string from @ the terminal @ R1: Points to a buffer to save the read string @ R2: Contains the number of the bytes to read @ LR: Contains the return address @ All registers are preserved. .global getstring @ Subroutine entry point. getstring: push {R0-R3,R7} @ Preserve working register contents. mov R0, #1 @ Code for stdin (standard input, i.e., keyboard) mov R7, #3 @ Linux service command code to read string. svc 0 @ Issue command to read string from stdin mov R2, #0 strb R2, [R1, R0] @ save a zero at the end of the string pop {R0-R3,R7} @ Restore saved register contents bx LR @ Return to the calling program. .end @ Subroutine Provided a pointer to a null terminated string, putstring will @ display the string to the terminal @ R1: Points to a null terminated string @ LR: Contains the return address @ All registers are preserved. .global putstring @ Subroutine entry point. putstring: push {R0-R3,R7} @ Preserve working register contents. mov R2, #0 @ R2 will store the length of the string. mov R3, R1 @ Copy R1 into R3 nxtchar: ldrb R0,[R3],#1 @ Load next character from string. subs R0, #0 @ Subtract the null bias. beq print @ if (zero flag is set) @ branch to print section @ else add R2, #1 @ increment length by 1 b nxtchar @ branch to top of loop print: mov R0, #1 @ Code for stdout (standard output, i.e., monitor) mov R7, #4 @ Linux service command code to write string. svc 0 @ Issue command to display string on stdout pop {R0-R3,R7} @ Restore saved register contents bx LR @ Return to the calling program. .end