Evaluation of a Given Arithmetic Expression
.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