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
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);
};
Similar Samples
At Programming Homework Help, we provide expertly crafted coding solutions tailored to your unique assignments. Our sample section showcases the high-quality work and attention to detail you can expect from our team, demonstrating our commitment to helping you excel in your programming courses.
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++
C++