我正在尝试创建一个 MARIE 代码,它等待用户输入的十进制数字,等待另一个输入,即 ASCII 字符 +、-、*、/(即 Dec 43、Dec 45、Dec 42、DEC) 47) 然后最后一个输入是另一个十进制数,然后求解所得出的方程。代码组装并开始,您可以输入所需的内容,但由于某种原因,加法是减法,其他一切都是加法。
下面是我的代码。
ORG 100 / Start of the program at address 100
/ Step 1: Get the first number (input)
Input / Wait for the first number
Store Num1 / Store the first number in memory (Num1)
/ Step 2: Get the operator (input)
Input / Wait for the operator (+, -, *, or /)
Store Operator / Store the operator in memory (Operator)
/ Step 3: Get the second number (input)
Input / Wait for the second number
Store Num2 / Store the second number in memory (Num2)
/ Step 4: Check the operator and perform the operation
Load Operator / Load the operator into the AC (accumulator)
Subt PlusOp / Check if the operator is '+'
Skipcond 400 / If the result is 0, it means it's '+'
Jump Addition / Jump to Addition section if operator is '+'
Load Operator / Load the operator into the AC again
Subt MinusOp / Check if the operator is '-'
Skipcond 400 / If the result is 0, it means it's '-'
Jump Subtraction / Jump to Subtraction section if operator is '-'
Load Operator / Load the operator into the AC again
Subt MultiplyOp / Check if the operator is '*'
Skipcond 400 / If the result is 0, it means it's '*'
Jump Multiply / Jump to Multiply section if operator is '*'
Load Operator / Load the operator into the AC again
Subt DivideOp / Check if the operator is '/'
Skipcond 400 / If the result is 0, it means it's '/'
Jump Divide / Jump to Division section if operator is '/'
/ Invalid operator (default to 0)
Clear / Clear the accumulator (result is 0)
Store Result / Store 0 as result
Jump OutputResult / Jump to output result
Addition, Load Num1
Add Num2 / Add Num1 and Num2
Store Result / Store the result in Result
Jump OutputResult / Jump to Output Result
Subtraction, Load Num1
Subt Num2 / Subtract Num2 from Num1 (correct subtraction)
Store Result / Store the result in Result
Jump OutputResult / Jump to Output Result
Multiply, Load Num1
Store Temp / Store the first number (Num1) in Temp
Load Num2
Store Counter / Store the second number (Num2) in Counter
/ Handle negative multiplier or multiplicand
Clear / Clear the accumulator
Store Result / Initialize Result to 0
Load Counter
Skipcond 800 / Check if the multiplier (Num2) is negative
Jump PositiveMultiply
/ If multiplier is negative, negate it
Load Counter
Subt Zero
Store Counter
Jump PositiveMultiply
PositiveMultiply, Load Temp
Add Result / Add Num1 to Result (this is equivalent to repeated addition)
Store Result / Store the intermediate result
Load Counter
Subt One
Store Counter / Decrease Counter (repeat the addition)
Skipcond 400 / If Counter is 0, end the loop
Jump PositiveMultiply
/ Store result and output it
OutputResult, Load Result
Output / Output the result
Halt / End of the program
/ Division by Repeated Subtraction
Divide, Load Num1 / Load the dividend (Num1) into AC
Store Quotient / Initialize Quotient to 0
Load Num2
Store Divisor / Store the divisor (Num2)
/ Check if the divisor is 0 (division by zero)
Load Divisor
Skipcond 800 / If divisor is 0, jump to division by zero handling
Jump DivisionLoop
DivisionByZero, Clear / Clear the result
Store Result / Store 0 as the result (division by zero)
Jump OutputResult / Jump to output result
DivisionLoop, Load Num1 / Load the dividend again
Subt Divisor / Subtract the divisor from the dividend
Skipcond 800 / If result is negative, stop the loop
Store Num1 / Update the dividend with the new value
Load Quotient
Add One / Increment the quotient by 1
Store Quotient / Store the updated quotient
Jump DivisionLoop / Repeat the loop
/ Store result and output it
Load Quotient
Store Result
Jump OutputResult
/ Memory Variables
Num1, Dec 0 / Store the first number
Num2, Dec 0 / Store the second number
Result, Dec 0 / Store the result
Temp, Dec 0 / Temporary storage for multiplication
Counter, Dec 0 / Counter for multiplication loop
Operator, Dec 0 / Store the operator
Quotient, Dec 0 / Store the quotient (division result)
Divisor, Dec 0 / Store the divisor
One, Dec 1 / Constant 1 for decrementing Counter
Zero, Dec 0 / Constant 0 for negating negative numbers
PlusOp, Dec 43 / ASCII for '+'
MinusOp, Dec 45 / ASCII for '-'
MultiplyOp, Dec 42 / ASCII for '*'
DivideOp, Dec 47 / ASCII for '/'
END
尝试更改
Skipcond
,但我不确定如何让它处理正确的算术。
100 + 50 最终是 50。
100 - 50 最终成为 150。
100 * 10 最终为 110。
100 / 10 最终为 110。
您误解了
SkipCond
的声明。当测试条件为 true 时,下一个语句是 skipped,这意味着它不会执行下面的 Jump
语句,这与您的假设相反。此错误发生在代码中的多个位置。
还有其他几个问题,包括但不限于:
第二个输入值可能为零,但您的乘法算法不能很好地处理它(
Counter
)为零的情况。在添加任何内容之前,您应该首先测试它是否为零。
Subt Zero
不会否定乘数;它一无所获。应该是 Clear
,然后是 Subt Counter
。
当乘数为负时取反后,结果会以错误的符号输出。你应该否定结果作为补偿。
仅使用说明内容超出说明内容的注释。应避免这样的评论:
Clear / Clear the accumulator
...因为这是您可以在手册中找到的内容。评论应集中于一组陈述的更高目标。
在除法循环中,您有一个
Skipcond 800
旨在退出循环,但它不会退出循环(没有 Jump
)。
如果您有注释“将商初始化为0”,则您没有这样做。商实际上应该从 0 开始,因为可能从一开始
Num1
就已经小于 Num2
。
除法算法中没有处理负操作数的规定。
由于您已经有一些用于在乘法情况下翻转第二个操作数的符号的代码,并且您需要两个除法操作数类似的代码,因此我建议在识别运算符是一个之前处理符号翻转乘法或除法,因此这两种情况都是通用的。然后,您可以存储一个标志来指示结果符号是否应在末尾翻转。
就像许多人在开始使用 MARIE 时所做的那样,您包含一个
ORG
指令。但它在这里确实没有任何作用——如果代码加载到默认地址 0 就没有问题。如果您被指示从不同的地址开始,则应在注释中记录其原因。
这是代码的大幅更新版本,可解决上述问题:
/ Initialise variables
Clear
Store FlipSign
Store Result
Input / Get input for the first operand
Store Num1
Input / Get input for the operator: either +, -, *, or /
Store Operator
Input / Get input for the second operand
Store Num2
/ Check the operator and perform the operation
Load Operator
Subt PlusOp / Check if the operator is '+'
Skipcond 400
Jump Case2 / It is not '+': check for other operators
Jump Add / It is '+': perform an addition
Case2, Load Operator
Subt MinusOp / Check if the operator is '-'
Skipcond 400
Jump Absolute / It is not '-': check the signs of operands
Jump Subtract / It is '-': perform a subtraction
/ Before checking for other operators, make the operands unsigned
Absolute, Load Num1 / Check the sign of Num1
SkipCond 000
Jump CheckSign2 / It is not negative: make the same check for Num2
Clear / It is negative: toggle the sign of Num1
Subt Num1
Store Num1
Load One / And update the flag that result must be flipped
Store FlipSign
CheckSign2, Load Num2 / Check the sign of Num2
SkipCond 000
Jump Case3 / It is not negative: continue with operator matching
Clear / It is negative: toggle the sign of Num2
Subt Num2
Store Num2
SkipCond 800 / Check if Num2 is strictly positive now
Jump OutputResult / No: Num2 is zero: we will output zero (covering also division by zero)
Load One / Num2 was made positive: toggle the flag to flip the result sign
Subt FlipSign
Store FlipSign / This will be 0 (don't flip) or 1 (flip)
/ Now that operands are unsigned, continue with operator checks
Case3, Load Operator
Subt MultiplyOp / Check if the operator is '*'
Skipcond 400
Jump Case4 / It is not '*': check for other operators
Jump Multiply / It is '*': perform a multiplication
Case4, Load Operator
Subt DivideOp / Check if the operator is '/'
Skipcond 400
Jump OutputResult / It is not '/': the operator is not valid: output 0
Jump Divide / It is '/': perform a division
Add, Load Num1
Add Num2 / Add Num1 and Num2
Store Result
Jump OutputResult
Subtract, Load Num1
Subt Num2 / Subtract Num2 from Num1
Store Result
Jump OutputResult
/ Multiplication by repeated addition
Multiply, Load Num2
Skipcond 800 / If more additions are remaining, continue the loop
Jump OutputResult / Otherwise, exit the loop
Subt One
Store Num2 / Decrease number of remaining additions
Load Result
Add Num1 / Add Num1 to Result
Store Result
Jump Multiply
/ Division by repeated subtraction
Divide, Load Num1
Subt Num2 / Subtract the divisor from the dividend
Skipcond 000
Jump DivisionNext / Num1 is not less than Num2, so continue
Jump OutputResult / Num1 is less than Num2; we have the final result
DivisionNext, Store Num1 / Update the dividend: Num1 -= Num2
Load Result
Add One / Increment the quotient by 1
Store Result
Jump Divide
/ Check whether we need to flip the sign of the result
OutputResult, Load FlipSign
SkipCond 800
Jump Output / The flag is not set: just output result
/ Flip sign
Clear
Subt Result
Store Result
Output, Load Result
Output
Halt
/ Constants
Zero, Dec 0
One, Dec 1
PlusOp, Dec 43 / ASCII for '+'
MinusOp, Dec 45 / ASCII for '-'
MultiplyOp, Dec 42 / ASCII for '*'
DivideOp, Dec 47 / ASCII for '/'
/ Variables
Num1, Dec 0 / For first input number
Num2, Dec 0 / For second input number
Operator, Dec 0 / For the operator character
Result, Dec 0 / For the result of the operation
FlipSign, Dec 0 / Flag for indicating that result sign should be flipped or not