-3

I am going through a problem I found on a website of making a calculator in LC-3. I am going about it in steps and saw something about doing what I am currently doing using stacks. I was wondering if someone could help me with what I have so far to convert it to using stacks, so far I have just been using registers! The code I have below is obviously incomplete, this is just what i have when i stopped and started researching on how to do some things. Here is my LC-3 Code for what I have so far:

        ;get first string from user
START   LEA R0, PROMPT1 ; Display the prompt
        PUTS
        LEA R0, BUFFER
        JSR READLINE

        ;convert string to number
        LEA R0, BUFFER
        JSR ATOI

        ;save the number
        ST  R0, FIRST_ARG

        ;get second string from user
        LEA R0, PROMPT2 ; Display the prompt
        PUTS
        LEA R0, BUFFER
        JSR READLINE

        ;convert string to number
        LEA R0, BUFFER
        JSR ATOI

        ;save the number
        ST  R0, SECOND_ARG

        ;load the arguments into R0 and R1
        LD  R0, FIRST_ARG
        LD  R1, SECOND_ARG

        JSR SUM 
PRINT_OUTPUT
        ;convert R0 into a string
        LEA R1, BUFFER
        JSR ITOA        ;not made yet, also will need division and subtraction subroutines

        ;print the sum of the two digits entered
        LEA R0, ANSWER  ; Display the prompt
        PUTS
        LEA R0, BUFFER
        PUTS

        ;print a new line character.
        LD  R0, ENTER
        OUT
STOP    HALT            ;

        ;subroutine SUM : calculates the sum of two numbers
        ;input: R0,R1
        ;output: R0 = R0 + R1
SUM
       ADD R0, R0, R1
       RET

        ;subroutine PROD : calculates the product of two numbers
        ;input: R0,R1
        ;output: R0 = R0 * R1
MUL
       ST  R2, MUL_SAVE_R2
       AND R2, R2, #0
       AND R1, R1, R1
MUL_START
       BRz MUL_END
       ADD R2, R2, R0
       ADD R1, R1, #-1
       BR  MUL_START
MUL_END
       ADD R0, R2, #0
       LD  R2, MUL_SAVE_R2
       RET
MUL_SAVE_R2 .FILL x0000

        ;subroutine READLINE : Reads a line of input from keyboard.
        ;input: R0. contains the address of the memory location where the
        ;   string must be placed.
READLINE
       ST  R7, RL_RETURN
       AND R1, R0, R0

RL_START
       ;get a character and echo it
       GETC
       OUT

       ;compare the character with ENTER which has ascii value 10
       ADD R2, R0, #-10
       BRz RL_END          ;the user typed ENTER, stop the loop
       STR R0, R1, #0      ;store whatever the user typed
       ADD R1, R1, #1      ;increment the pointer
       BR  RL_START
RL_END
       AND R0, R0, #0
       STR R0, R1, #0      ;write the null character
       LD  R7, RL_RETURN
       RET
RL_RETURN  .FILL x0000

;subroutine ATOI : Converts an ASCII string to an integer
;input: R0, contains the address of the string
;output: R0, should contain the integer value
ATOI
       ST  R7, ATOI_RETURN

       AND R2, R0, R0      ;R2 <- R0;
       AND R0, R0, #0      ;R0 <- 0
       ADD R1, R0, #10     ;R1 <- 10

       LD  R4, ASCIIZERO
       NOT R4, R4
       ADD R4, R4, #1      ;This is to convert ascii character to integer

ATOI_START
       LDR R5, R2, #0
       BRz ATOI_END        ;we've reached the end of the string

       AND R1, R1, #0
       ADD R1, R1, #10     ;R1 <- 10
       JSR MUL            ;multiply current number by 10

       ADD R5, R5, R4      ;subtract ASCIIZERO from R5
       BRn INVALID_INPUT   ;user typed something less than '0'
       ADD R6, R5, #-9
       BRp INVALID_INPUT   ;user typed something more than '9'

       ADD R0, R0, R5
       ADD R2, R2, #1      ;next character
       BR  ATOI_START
INVALID_INPUT
       AND R0, R0, #0      ;make R0 <- -1
       ADD R0, R0, #-1
ATOI_END
       LD  R7, ATOI_RETURN
       RET

ATOI_RETURN .FILL x0000


;allocate memory for the input
FIRST_ARG  .FILL x0000
SECOND_ARG .FILL x0000
BUFFER     .BLKW #15  ; allocating memory for storing user input.

POP
        LDR R0, R6, #0
        ADD R6, R6, #1
        RET

PUSH
        ADD R6, R6, #-1
        STR R0, R6, #0
        RET

;constants
MINUS      .FILL x002D; '-'
ENTER      .FILL x000A; newline character
PROMPT1    .STRINGZ "Please input the first digit > "
PROMPT2    .STRINGZ "Please input the second digit > "
ANSWER     .STRINGZ "Sum of the two digits entered = "
ASCIIZERO  .FILL x0030; '0'
.END
connor moore
  • 611
  • 1
  • 8
  • 18
  • You should ask a more specific question. EDIT: I see you already have push and pop. – Jester Dec 09 '14 at 23:43
  • "Here is my code so far" is not a valid question for stackoverflow. You must say what problem you are actually having and where in the code that problem is. There is an auto-ban for users who have too many questions closed (hint, its only 2 or 3 questions) – JK. Dec 10 '14 at 00:45

2 Answers2

0

A straightforward way to make a calculator is to make one that uses Reverse Polish Notation (RPN).

When you use RPN you read in the input token by token and perform an action after each read. If the token is a number, push it on to the stack. If it is an operator, pop elements off the stack and process them. For example, if the operator is +, pop the top two elements on the stack and add them, pushing the sum on to the stack. When you have finished reading tokens, the top element on the stack is your answer.

To make it easier to get the tokens, perhaps require that tokens be separated by a single space (at least to start with).

So, for instance, the user might enter:

7 5 + 12 /

You would:

  1. Read token 7 and push it (stack is now 7)
  2. Read token 5 and push it (stack is now 5,7)
  3. Read token +, pop 7 and 5 into registers, add them, push the result (stack is now 12)
  4. Read token 12 and push it (stack is now 12,12)
  5. Read token /, pop 12 and 12 into registers, divide them, push the result (stack is now 1).
  6. Pop the final answer into a register and print the result (1).

The Unix utility dc works like this (or works as if it does, at least).

Using other kinds of notation, including the standard "infix" notation, will be more difficult. I think the most excellent The C++ Programming Language has (or had in an earlier edition if it doesn't now) a toy example of an infix calculator, to give you an idea of what would be involved.

Tony
  • 1,645
  • 1
  • 10
  • 13
0

If you're asking about passing variables to functions on the stack then for one thing, you don't need to. Using registers is what optimizers would aspire to.

However, the mechanism is to push them onto the stack (R13), call the function and then, add return, add the size of the variables to the stack pointer (2 x 32 bit numbers = 8 bytes).

I believe in ARM, the frame pointer (R11) automatically points to the stack before the function was called. So, if 2 x 32bit numbers numbers were pushed onto the stack, the first would at [R11, #-8] and the second at [R11, #-4] (remember that stacks grow from the end).

Mike
  • 2,721
  • 1
  • 15
  • 20