Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <deque>
- #include <map>
- #include <string>
- #include <utility>
- #include <sstream>
- #include <stdlib.h>
- using namespace std;
- enum OpCode{
- AM_READ=0,
- AM_WRITE,
- AM_LOAD,
- AM_STORE,
- AM_LIT,
- AM_ADD,
- AM_MUL,
- AM_SUB,
- AM_DIV,
- AM_MOD,
- AM_LT,
- AM_EQ,
- AM_NE,
- AM_GT,
- AM_LE,
- AM_GE,
- AM_JMP,
- AM_JMC
- };
- struct Befehl {
- OpCode op;
- int right;
- };
- class Programm;
- class CException{
- public:
- CException() {}
- ~CException() {}
- static void AbnormalProgramTermination(string cerr)
- {
- cout << "Fatal Error: " << cerr << endl;
- cout << "Please enter any number to exit the program: ";
- int foo;
- cin >> foo;
- exit(-1);
- }
- };
- template<class T> class VirtualMachine{
- public:
- VirtualMachine(Programm * vater) : m_befehlszaehler(1) {
- m_vater = vater;
- }
- unsigned int Tick(Befehl * cmd)
- {
- switch(cmd->op)
- {
- case AM_READ:
- if(!m_eingabeband.size())
- CException::AbnormalProgramTermination("READ trotz leerem Eingabeband");
- m_hauptspeicher[cmd->right] = m_eingabeband[0];
- m_eingabeband.pop_front();
- ++m_befehlszaehler;
- break;
- case AM_WRITE:
- if(m_hauptspeicher.find(cmd->right) == m_hauptspeicher.end())
- CException::AbnormalProgramTermination("WRITE zeigt auf ungueltigen Wert");
- m_ausgabeband.push_back(m_hauptspeicher[cmd->right]);
- ++m_befehlszaehler;
- break;
- case AM_LOAD:
- if(m_hauptspeicher.find(cmd->right) == m_hauptspeicher.end())
- CException::AbnormalProgramTermination("LOAD zeigt auf ungueltigen Wert");
- m_datenkeller.push_front(m_hauptspeicher[cmd->right]);
- ++m_befehlszaehler;
- break;
- case AM_STORE:
- if(!m_datenkeller.size())
- CException::AbnormalProgramTermination("STORE trotz leerem Datenkeller");
- m_hauptspeicher[cmd->right] = m_datenkeller[0];
- m_datenkeller.pop_front();
- ++m_befehlszaehler;
- break;
- case AM_LIT:
- m_datenkeller.push_front(cmd->right);
- ++m_befehlszaehler;
- break;
- case AM_ADD: case AM_MUL: case AM_SUB: case AM_DIV: case AM_MOD: case AM_LT: case AM_EQ: case AM_NE: case AM_GT: case AM_LE: case AM_GE:
- if(m_datenkeller.size() <= 1)
- CException::AbnormalProgramTermination("OP trotz kleinem Datenkeller");
- if(cmd->op == AM_ADD) m_datenkeller[1] = m_datenkeller[1] + m_datenkeller[0];
- if(cmd->op == AM_MUL) m_datenkeller[1] = m_datenkeller[1] * m_datenkeller[0];
- if(cmd->op == AM_SUB) m_datenkeller[1] = m_datenkeller[1] - m_datenkeller[0];
- if(cmd->op == AM_DIV) m_datenkeller[1] = m_datenkeller[1] / m_datenkeller[0];
- if(cmd->op == AM_MOD) m_datenkeller[1] = m_datenkeller[1] % m_datenkeller[0];
- if(cmd->op == AM_LT) m_datenkeller[1] = m_datenkeller[1] < m_datenkeller[0];
- if(cmd->op == AM_EQ) m_datenkeller[1] = m_datenkeller[1] == m_datenkeller[0];
- if(cmd->op == AM_NE) m_datenkeller[1] = m_datenkeller[1] != m_datenkeller[0];
- if(cmd->op == AM_GT) m_datenkeller[1] = m_datenkeller[1] > m_datenkeller[0];
- if(cmd->op == AM_LE) m_datenkeller[1] = m_datenkeller[1] <= m_datenkeller[0];
- if(cmd->op == AM_GE) m_datenkeller[1] = m_datenkeller[1] >= m_datenkeller[0];
- m_datenkeller.pop_front();
- ++m_befehlszaehler;
- break;
- case AM_JMP:
- m_befehlszaehler = cmd->right;
- break;
- case AM_JMC:
- if(!m_datenkeller.size())
- CException::AbnormalProgramTermination("JMC trotz leerem Datenkeller");
- int flag = m_datenkeller[0]; m_datenkeller.pop_front();
- if(flag != 0 && flag != 1)
- CException::AbnormalProgramTermination("JUMP FLAG OUT OF BOUNDS");
- if(flag == 0)
- m_befehlszaehler = cmd->right;
- else
- ++m_befehlszaehler;
- break;
- }
- return m_befehlszaehler;
- }
- deque<T> & Ausgabeband() {return m_ausgabeband;}
- deque<T> & Eingabeband() {return m_eingabeband;}
- deque<T> & Datenkeller() {return m_datenkeller;}
- map<unsigned int, T> & HauptSpeicher() {return m_hauptspeicher;}
- unsigned int Pos() {return m_befehlszaehler;}
- string HauptSpeicherString()
- {
- stringstream ss;
- ss << "[";
- map<unsigned int, T>::iterator it, it2;
- for ( it=m_hauptspeicher.begin() ; it != m_hauptspeicher.end(); it++ )
- {
- ss << (*it).first << "/" << (*it).second;
- it2 = it;
- if(++it2!=m_hauptspeicher.end())
- ss << ",";
- }
- ss << "]";
- return ss.str();
- }
- string DequePrint(deque<T> & deq, char separator=':')
- {
- stringstream ss;
- if(!deq.size()) return "e";
- for(unsigned int i = 0; i < deq.size(); ++i)
- {
- ss << deq[i];
- if(i != deq.size()-1)
- ss << separator;
- }
- return ss.str();
- }
- private:
- unsigned int m_befehlszaehler;
- deque<T> m_datenkeller;
- map<unsigned int, T> m_hauptspeicher;
- deque<T> m_eingabeband;
- deque<T> m_ausgabeband;
- Programm * m_vater;
- };
- class Programm{
- public:
- Programm() {m_machine = new VirtualMachine<int>(this);}
- ~Programm() {delete m_machine;}
- void CmdReg(OpCode op, int rop)
- {
- Befehl nb;
- nb.op = op;
- nb.right = rop;
- m_programm.push_back(nb);
- }
- void LegeAufEingabeband(int k)
- {
- m_machine->Eingabeband().push_front(k);
- }
- void LadeProgramm()
- {
- LegeAufEingabeband(123);
- pair<OpCode,int> programm[] = {
- pair<OpCode,int>(AM_READ,1),
- pair<OpCode,int>(AM_LIT,0),
- pair<OpCode,int>(AM_STORE,2),
- pair<OpCode,int>(AM_LOAD,1),
- pair<OpCode,int>(AM_LIT,0),
- pair<OpCode,int>(AM_NE,0xCC),
- pair<OpCode,int>(AM_JMC,25),
- pair<OpCode,int>(AM_LOAD,1),
- pair<OpCode,int>(AM_LIT,10),
- pair<OpCode,int>(AM_MOD,0xCC),
- pair<OpCode,int>(AM_STORE,3),
- pair<OpCode,int>(AM_LOAD,3),
- pair<OpCode,int>(AM_LIT,2),
- pair<OpCode,int>(AM_MOD,0xCC),
- pair<OpCode,int>(AM_JMC,20),
- pair<OpCode,int>(AM_LOAD,3),
- pair<OpCode,int>(AM_LOAD,2),
- pair<OpCode,int>(AM_ADD,0xCC),
- pair<OpCode,int>(AM_STORE,2),
- pair<OpCode,int>(AM_LOAD,1),
- pair<OpCode,int>(AM_LIT,10),
- pair<OpCode,int>(AM_DIV,0xCC),
- pair<OpCode,int>(AM_STORE,1),
- pair<OpCode,int>(AM_JMP,4),
- pair<OpCode,int>(AM_WRITE,2),
- };
- for(int i = 0; i < sizeof(programm)/sizeof(programm[0]); ++i)
- CmdReg(programm[i].first,programm[i].second);
- }
- void Debug()
- {
- cout << "( " << m_machine->Pos() << " , " << m_machine->DequePrint(m_machine->Datenkeller()) << " , "
- << m_machine->HauptSpeicherString() << " , " << m_machine->DequePrint(m_machine->Eingabeband()) << " , "
- << m_machine->DequePrint(m_machine->Ausgabeband()) << " )" << endl;
- }
- void FuehreProgrammAus()
- {
- int iPos = 1;
- for(int i = 0; i < 200 && iPos < 1+m_programm.size(); ++i) //WHILE NOT EOF
- {
- Debug();
- iPos = m_machine->Tick(&P(iPos));
- }
- Debug();
- }
- Befehl P(unsigned int i) {
- --i;
- if(i < m_programm.size())return m_programm[i];
- else{
- cout << "Fataler Fehler: EOP " << i << endl;
- return m_programm[0];
- }
- }
- private:
- VirtualMachine<int> * m_machine;
- vector<Befehl> m_programm;
- };
- int main()
- {
- Programm foo;
- foo.LadeProgramm();
- foo.FuehreProgrammAus();
- system("pause");
- }
Add Comment
Please, Sign In to add comment