Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- PRESERVE8
- AREA MyCode, CODE, READONLY
- EXPORT calc
- calc
- import my_fprint
- import my_getchar
- import my_putchar
- mov r0, #0x0A
- BL my_fprint
- LDR r0,=cal ;"NEW CALCULATOR"
- BL my_fprint ;prints cal and empties register
- resetarg
- LDR r8, =arg ;load address of the argument in r8
- get_new
- MOV r10, #0 ;register to store argument
- BL my_getchar
- MOV r10,r0
- BL my_putchar
- CMP r10, #0x0D ;CR
- BEQ Ascii ;if cr -> end of number -> convert ascii to int
- CMP r10, #"="
- BEQ equals ;breaks if character entered is "="
- CMP r10, #0x30
- BLT op ;assume '+', '-', '/', '*' only op lt 0x30
- cmp r10, #0x39 ;if gt 0x39 and not "=", invalid character
- bgt inv_op
- STR r10, [r8], #4 ;store input in arg
- ADD r6,r6,#1 ;string counter
- B get_new ;if char entered not op or CR, get next digit
- Ascii
- LDR r8, =arg
- MOV r0, #0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- MOV r1, #0
- MOV r2, #0
- MOV r3, #0
- AsciiToDec
- LDRB r2, [r8],#4 ;loads r8 into r2, updates memory address
- SUB r2, r2, #0x30 ;subtracts 0x30 (0x35 = 5, 0x37 = 7, etc.)
- LSL r3,r1,#3 ;multiplies previous input by 8
- ADD r1,r3,r1, LSL #1;r1 = previous input *10
- ADD r1, r2, r1 ;adds previous input *10 to current input
- SUB r6,r6,#1 ;decrement string counter
- CMP r6, #0 ;check if end of string is reached
- BNE AsciiToDec ;keep going if not
- PUSH {r1} ;pushes final converted value onto stack
- B resetarg ;get next argument
- op
- CMP r6, #0
- BNE inv_op
- CMP r10,#"+"
- BEQ plus
- CMP r10,#"-"
- BEQ minus
- CMP r10,#"/"
- BEQ div
- CMP r10,#"*"
- BEQ mult
- inv_op
- MOV r0, #0x0A ;LF
- BL my_putchar ;outputs line feed
- LDR r0, =Inv ;prints error message
- BL my_fprint
- B stop
- equals
- BL my_getchar
- CMP r0,#0x0D ;verifies that the next character is an enter
- BNE inv_op ;if not then the format is incorrect
- BL my_putchar
- MOV r0,#0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- B Reset
- plus
- BL my_getchar
- CMP r0,#0x0D ;verifies that the next character is an enter
- BNE inv_op ;if not then the format is incorrect
- BL my_putchar ;beginning of line
- MOV r0,#0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- POP {r5}
- POP {r7}
- ADD r5,r7,r5 ;ADD arguments
- PUSH {r5}
- B get_new ;return from subroutine
- minus
- BL my_getchar
- CMP r0,#0x0D ;verifies that the next character is an enter
- BNE inv_op ;if not then the format is incorrect
- BL my_putchar ;beginning of line
- MOV r0,#0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- POP {r5}
- POP {r7}
- cmp r7, r5
- blt NegRes ;if negative, call function to switch argument order and add negative flag
- SUB r5,r7,r5 ;subtract arguments if result is positive
- PUSH {r5}
- B get_new ;return from subroutine
- NegRes
- sub r5, r5, r7 ;switches order of subtraction
- push {r5} ;pushes result onto stack
- mov r12, #"-" ;sets negative flag
- b get_new
- div
- BL my_getchar
- CMP r0,#0x0D ;verifies that the next character is an enter
- BNE inv_op ;if not then the format is incorrect
- BL my_putchar ;beginning of line
- MOV r0,#0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- POP {r5}
- POP {r7}
- SDIV r5,r7,r5 ;divide arguments
- PUSH {r5}
- B get_new ;return from subroutine
- mult
- BL my_getchar
- CMP r0,#0x0D ;verifies that the next character is an enter
- BNE inv_op ;if not then the format is incorrect
- BL my_putchar ;beginning of line
- MOV r0,#0x0A ;LF
- BL my_putchar ;outputs line feed between new things
- POP {r5}
- POP {r7}
- MUL r5,r7,r5 ;multiply arguments
- PUSH {r5}
- B get_new ;return from subroutine
- Reset
- pop {r4} ;gets final value to be outputted from stack
- MOV r6, #10 ;stores 10 in r6
- MOV r1, r4 ;stores final value in r4
- MOV r11, #0 ;reset r11
- LDR r7, =ToMemory ;r7 will contain values stored to memory
- AsciiToInt
- UDIV r1, r1, r6 ;divides the value by 10 and stores the result in r1 - eg 1035/10 -> 103 in r1
- LSL r9, r1, #3
- ADD r8, r9, r1, LSL#1 ;this line and the previous multiply the value by 10
- SUB r3, r4, r8 ;obtains the remainder of the division
- ADD r10, r3, #0x30 ;converts the remainder into ascii
- STR r10, [r7], #4 ;stores the ascii value of the remainder into memory to be printed later
- MOV r4, r1 ;updates the numerator value for the next iteration
- ADD r11, r11, #1 ;string counter
- CMP r1, #9
- BGT AsciiToInt ;if the new numerator is >10, iterate. If not, simply store it in memory
- ADD r1, r1, #0x30 ;converts the numerator to ascii when it is <10
- STR r1, [r7] ;stores it in memory
- ADD r11, r11, #1 ;string counter
- PrintAscii
- LDR r0, [r7], #-4 ;little-endian, starts loading from the final value stored in memory from previous subroutine
- BL my_putchar ;prints it
- SUB r11, r11, #1 ;decrement string counter
- CMP r11, #0 ;check string counter
- BNE PrintAscii ;continue if not 0
- cmp r12, #"-" ;checks negative flag
- bne stop ;if not equal result is positive - stop
- NegFlag
- mov r0, #"-" ;prints negative sign
- bl my_putchar
- B stop
- stop
- B stop
- ALIGN ;aligns code (but also data) to a memory boundary
- AREA MyData, DATA, READWRITE
- cal DCB "Type the RPN expression with Enter after each argument and operator",0
- Inv DCB "Invalid operation",0
- arg SPACE 100
- ToMemory space 100
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement