+1 (315) 557-6473 

Program to Simulate Very Simple Stack Based Assembly (Push Value, Or Arithmetic Operation Only) In C++ Language Assignment Solution.


Instructions

Objective
Write a C++ program to simulate very simple stack based assembly (push value, or arithmetic operation only).

Requirements and Specifications 

For this assignment you will implement a simplified stack-based CPU. You must implement your own stack data structure (do not use std::stack). Your program will read in a program and produce an output. Your CPU must implement the following functionality:
void LoadProgram(string filename) -- loads a program stored in the filename location. Ensures that the stack is empty and any previous program is removed.
int Run ()-- runs the entire program and returns the final value (the only one left in the stack). If there is more than one value in the stack, throw an error.
int Next() - - runs the next line of the program and returns O. If there are no more lines it returns - 1.
Overload the << operator - - prints the current stack.
Your CPU must support the following language. All values are only integers. If an operation takes two inputs from the stack and there aren't two inputs, then throw an error.
PSH val - - pushes val onto the stack.
ADD -- Pops the top two values from the stack and pushes the sum of them onto the stack
MULT - - Pops the top two values from the stack and pushes the product of them onto the stack
SUB -- Pops the top two values from the stack and pushes the difference of the second value minus the first onto the stack
DIV - - Pops the top two values from the stack and pushes the second value divided by the first onto the stack (note: only the integer portion). Div by O should throw an error.
CMP -- Pops the top two values from the stack. If the first is greater than the second, push 1. If they are equal, push O, if the second is greater than the first, push -1.
Screenshots of output 
Simulate stack based assembly in C++

Source Code

cpu.cpp

#include "cpu.h"

#include

#include

#include

#include

#include

// CPU class constructor

CPU::CPU()

{

    stack = new Stack();

    progSize = 0;

    curInst = 0;

    error = false;

}

// CPU class destructor

CPU::~CPU()

{

    delete stack;

    if (progSize != 0) // if there was a program before, delete it

    {

        for (int i = 0; i < progSize; i++)

            delete program[i];

        delete [] program;

    }

}

// Load program to CPU. Empties stack and removes previous program if any.

void CPU::LoadProgram(std::string filename)

{

    std::ifstream file(filename.c_str());

    if (!file.is_open())

        throw std::runtime_error("ERROR: Unable to open file: \"" + filename + "\"");

    std::string line;

    // if there was a program before, delete it

    if (progSize != 0)

    {

        for (int i = 0; i < progSize; i++)

            delete program[i];

        delete [] program;

    }

    // get file size

    progSize = 0;

    while (std::getline(file, line))

    {

        if (line.length() != 0)

            progSize++;

    }

    file.clear();

    file.seekg(0, file.beg); // rewind file pointer to start

    program = new Instruction*[progSize]; // create array of instructions

    // load program from file

    int i = 0;

    while (std::getline(file, line))

    {

        if (line.length() != 0)

        {

            std::string name;

            int operand = 0;

            std::stringstream ss(line);

            ss >> name; // read instruction name

            if (name == "PSH")

            {

                ss >> operand; // read operand

            }

            else if (name != "ADD" && name != "MULT" && name != "SUB" &&

                    name != "DIV" && name != "CMP")

                throw std::runtime_error("ERROR: Invalid instruction: \"" + name + "\"");

            program[i++] = new Instruction(name, operand);

        }

    }

    file.close();

    // empty the stack if it's not empty

    while (!stack->isEmpty())

        stack->pop();

    // reset current instruction counter

    curInst = 0;

    error = false;

}

// Runs the entire program and returns the final value in the stack. Throws an

// error if there is more than one value left in the stack.

int CPU::Run()

{

    if (error)

        return 0;

    while (Next() == 0 && !error);

    if (!error)

    {

        if (stack->isEmpty())

        {

            std::cout << "ERROR: stack is empty after run";

            error = true;

            return 0;

        }

        int val = stack->pop();

        if (!stack->isEmpty())

        {

            std::cout << "ERROR: stack is not empty after run";

            error = true;

        }

        return val;

    }

    return 0;

}

// Runs the next line in the program and returns 0. If there are no more lines

// returns -1

int CPU::Next()

{

    if (error)

        return -1;

    if (curInst < progSize)

    {

        int a, b;

        std::string name = program[curInst]->getName();

        try {

            if (name == "PSH")

            {

                stack->push(program[curInst]->getOperand());

            }

            else if (name == "ADD")

            {

                a = stack->pop();

                b = stack->pop();

                stack->push(a + b);

            }

            else if (name == "MULT")

            {

                a = stack->pop();

                b = stack->pop();

                stack->push(a * b);

            }

            else if (name == "SUB")

            {

                a = stack->pop();

                b = stack->pop();

                stack->push(b - a);

            }

            else if (name == "DIV")

            {

                a = stack->pop();

                b = stack->pop();

                if (a == 0)

                {

                    std::cout << "ERROR: Division by zero\n";

                    error = true;

                    return -1;

                }

                stack->push(b / a);

            }

            else if (name == "CMP")

            {

                a = stack->pop();

                b = stack->pop();

                if (a > b)

                    stack->push(1);

                else if (a == b)

                    stack->push(0);

                else

                    stack->push(-1);

            }

            curInst++;

            return 0;

        } catch (const std::exception& e) {

            std::cout << "ERROR: missing stack argument for " << name << "\n";

            error = true;

            return -1;

        }

    }

    return -1;

}

std::ostream& operator <<(std::ostream& os, const CPU& cpu)

{

    os << *cpu.stack;

    return os;

}

// Implementation of the Stack data structure

// Stack constructor

Stack::Stack()

{

    cur_size = 100;

    data = new int[cur_size];

    size = 0;

}

// Stack destructor

Stack::~Stack()

{

    delete [] data;

}

// Add new data on top of the stack

void Stack::push(int x)

{

    if (size >= cur_size) // if allocated space is not enough

    {

        cur_size *= 2; // double stack size

        int *new_data = new int[cur_size]; // allocate larger space

        for (int i = 0; i < size; i++) // copy old data

            new_data[i] = data[i];

        delete [] data; // free old data

        data = new_data; // use newluy allocated space

    }

    data[size++] = x; // save on top

}

// Remove the value at the top of the stack

int Stack::pop()

{

    if (size == 0) // if empty stack

        throw std::runtime_error("ERROR: Pop on empty stack");

    size--; // decrement stack size

    return data[size]; // return top value

}

// Returns true of the stack is empty

bool Stack::isEmpty()

{

    return (size == 0);

}

// Print the stack

std::ostream& operator <<(std::ostream& os, const Stack& stack)

{

    os << "Stack: [ ";

    for (int i = 0; i < stack.size; i++)

    {

        if (i != 0)

            os << ", ";

        os << std::dec << stack.data[i];

    }

    os << " ]";

    return os;

}

// Implementation of the Instruction class

// Constructor of the Instruction class

Instruction::Instruction(std::string name, int operand)

{

    this->name = name;

    this->operand = operand;

}

// Returns the type of the instruction

std::string Instruction::getName()

{

    return name;

}

// Returns the operand for the instruction

int Instruction::getOperand()

{

    return operand;

}

cpu.h

#pragma once

#include

#include

// Definition of the class for the stack

class Stack

{

    int *data; // array of integers

    int size; // number of current elements in stack

    int cur_size; // size of allocated array

public:

    Stack();

    ~Stack();

    void push(int x);

    int pop();

    bool isEmpty();

    friend std::ostream& operator <<(std::ostream& os, const Stack& stack);

};

// Definition of the instruction class

class Instruction

{

    std::string name; // instruction name

    int operand; // operand for PSH

public:

    Instruction(std::string name, int operand);

    std::string getName();

    int getOperand();

};

// Definition of the CPU class

class CPU

{

    Stack *stack; // stack

    Instruction **program; // loaded program

    int curInst; // current instruction

    int progSize; // size of loaded program

    bool error; // indicates if an execution error has occurred

public:

    CPU();

    ~CPU();

    void LoadProgram(std::string filename);

    int Run();

    int Next();

    friend std::ostream& operator <<(std::ostream& os, const CPU& cpu);

};