EeryTester87
EeryTester87

Reputation: 1

Perform addition, subtraction, multiplication or division based on user choice. Why when user chooses addition, a subtraction is executed?

I am trying to create a MARIE Code that waits for an INPUT from a user that is a decimal number, waits for another INPUT that are ASCII characters +,-,*,/ (being Dec 43, Dec 45, Dec 42, DEC 47) and then the last INPUT being another decimal number then solves the equation made. The code Assembles and Starts and you are able to input what is needed but for some reason Addition is Subtraction and everything else is Addition.

Below is the code I have.

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

Tried changing the Skipcond but I'm not sure how to get it to process the correct Arithmetic.

100 + 50 ends up being 50.

100 - 50 ends up being 150.

100 * 10 ends up being 110.

100 / 10 ends up being 110.

Upvotes: 0

Views: 52

Answers (1)

trincot
trincot

Reputation: 350252

You've misinterpreted the SkipCond statement. When the tested condition is true, then the next statement is skipped, meaning it does not perform the Jump statement you have below it, which is the opposite from what you have assumed. This mistake occurs at several places in your code.

There are several other issues, including, but not limited to:

  • The second input value may be zero, but your multiplication algorithm does not deal well with the case where it (Counter) is zero. You should first test whether it is zero before adding anything.

  • Subt Zero does not negate the multiplier; it achieves nothing. It should be Clear followed by Subt Counter.

  • After you negate the multiplier when it is negative, the result is output with the wrong sign. You should negate the result as compensation.

  • Only use comments that tell something more than just what the instruction does. A comment like this should be avoided:

    Clear / Clear the accumulator
    

    ... as that is something you can find in the manual. Comments should focus on the higher goal of a set of statements.

  • In the division loop you have a Skipcond 800 with the intention to exit the loop, but it doesn't exit the loop (there is no Jump).

  • Where you have the comment "Initialize Quotient to 0", you are not doing that. The quotient should really start with 0, as it might be that Num1 is already less than Num2 from the very start.

  • In the division algorithm there is no provision to deal with negative operands.

    As you already have some code for flipping the sign of the second operand for the case of multiplication, and you would need something similar for both of the division operands, I would suggest to deal with sign-flipping just before identifying the operator is a multiplication or division, so that it is common for both cases. You could then store a flag to indicate whether the result sign should be flipped at the end or not.

  • Like many do when starting with MARIE, you include an ORG directive. But it really does not serve a purpose here -- there is no problem if the code is loaded at the default address 0. If you were instructed to start at a different address, the reason for this should be documented in a comment.

Here is a heavily updated version of your code that addresses the above issues:

              / 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

Upvotes: 1

Related Questions