我正在经历一个在LC-3上制作计算器的网站上发现的问题。我正在逐步进行,并看到了一些关于使用堆栈做我目前正在做的事情。我想知道是否有人可以帮助我到目前为止将其转换为使用堆栈,到目前为止我一直在使用寄存器!我下面的代码显然是不完整的,这就是我停下来开始研究如何做某些事情时所拥有的。这是我目前的LC-3代码:
;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
答案 0 :(得分:0)
制作计算器的一种简单方法是制作一个使用Reverse Polish Notation(RPN)的计算器。
使用RPN时,您可以通过令牌读入输入令牌,并在每次读取后执行操作。如果令牌是数字,则将其推入堆栈。如果它是一个操作符,则从堆栈中弹出元素并处理它们。例如,如果运算符为+
,则弹出堆栈中的前两个元素并添加它们,将总和推送到堆栈。完成阅读令牌后,堆栈中的顶部元素就是您的答案。
为了更容易获得令牌,可能需要将令牌分隔为一个空格(至少从一开始)。
因此,例如,用户可能会输入:
7 5 + 12 /
你会:
7
和push
它(堆栈现在为7
)5
和push
它(现在是堆栈5
,7
)+
,将7
和5
弹出到寄存器中,添加它们,push
结果(堆栈现在为12
)12
和push
它(现在是堆栈12
,12
)/
,pop
12
和12
读入寄存器,将它们分开,push
结果(堆栈现在为1
) Pop
最终答案进入注册表并打印结果(1
)。 Unix实用程序dc
的工作方式与此类似(或者至少可以正常工作)。
使用其他类型的表示法,包括标准&#34;中缀&#34;符号,会更难。我认为最优秀的The C++ Programming Language(或者在早期版本中,如果它现在还没有)是一个中缀计算器的玩具示例,可以让您了解所涉及的内容。
答案 1 :(得分:0)
如果您要求将变量传递给堆栈上的函数,那么一方面,您不需要。使用寄存器是优化器所希望的。
然而,机制是将它们推入堆栈(R13),调用函数然后,添加return,将变量的大小添加到堆栈指针(2 x 32位数= 8字节)。
我相信在ARM中,帧指针(R11)在调用函数之前自动指向堆栈。因此,如果2 x 32位数字被推入堆栈,第一个将在[R11,# - 8],第二个在[R11,#-4](请记住堆栈从末尾开始增长)。