📄 virtualmachine.cpp
字号:
// VirtualMachine.cpp: implementation of the CVirtualMachine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "zscpascal.h"
#include "VirtualMachine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// The Instruction names, for the ASM generation
CString CVirtualMachine::m_stInstNames[INSTR_NUMBER] =
{
_T("NOP"),
_T("OR"),
_T("OUTP"),
_T("INP"),
_T("ERR"),
_T("STOP"),
_T("RET"),
_T("CALL"),
_T("MOD"),
_T("DIV"),
_T("MUL"),
_T("SUB"),
_T("ADD"),
_T("NEQ"),
_T("EQU"),
_T("GEQ"),
_T("GRT"),
_T("LEQ"),
_T("LES"),
_T("FJP"),
_T("UJP"),
_T("RED"),
_T("MVRX"),
_T("STO"),
_T("COPY"),
_T("LODIX"),
_T("LODI"),
_T("LOD"),
_T("AND"),
_T("ENTER"),
_T("LEAVE"),
_T("CHGSFP"),
_T("RSTSFR"),
_T("LODA"),
_T("LODAX"),
_T("LODEA"),
_T("USTO"),
_T("PUSH"),
_T("POP"),
_T("NFJP")
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// construction, specify the memory size of the machine (default 16k)
CVirtualMachine::CVirtualMachine(int memSize)
{
m_ST = 0;
m_bTrap = FALSE;
m_nMemSize = memSize;
m_pbMem = new BYTE[memSize];
// The memory content is initialized with STOP instructions
for(int i = 0; i< memSize; i++)
m_pbMem[i] = INSTR_STOP;
// Initializing the instruction table
m_Execute[INSTR_NOP] = NOP;
m_Execute[INSTR_AND] = AND;
m_Execute[INSTR_OR] = OR;
m_Execute[INSTR_OUTP] = OUTP;
m_Execute[INSTR_INP] = INP;
m_Execute[INSTR_ERR] = ERR;
m_Execute[INSTR_STOP] = STOP;
m_Execute[INSTR_RET] = RET;
m_Execute[INSTR_CALL] = CALL;
m_Execute[INSTR_MOD] = MOD;
m_Execute[INSTR_DIV] = DIV;
m_Execute[INSTR_MUL] = MUL;
m_Execute[INSTR_SUB] = SUB;
m_Execute[INSTR_ADD] = ADD;
m_Execute[INSTR_NEQ] = NEQ;
m_Execute[INSTR_EQU] = EQU;
m_Execute[INSTR_GEQ] = GEQ;
m_Execute[INSTR_GRT] = GRT;
m_Execute[INSTR_LEQ] = LEQ;
m_Execute[INSTR_LES] = LES;
m_Execute[INSTR_FJP] = FJP;
m_Execute[INSTR_UJP] = UJP;
m_Execute[INSTR_RED] = RED;
m_Execute[INSTR_MVRX] = MVRX;
m_Execute[INSTR_STO] = STO;
m_Execute[INSTR_COPY] = COPY;
m_Execute[INSTR_LODIX] = LODIX;
m_Execute[INSTR_LODI] = LODI;
m_Execute[INSTR_LOD] = LOD;
m_Execute[INSTR_LODA] = LODA;
m_Execute[INSTR_LODAX] = LODAX;
m_Execute[INSTR_LODEA] = LODEA;
m_Execute[INSTR_USTO] = USTO;
m_Execute[INSTR_PUSH] = PUSH;
m_Execute[INSTR_POP] = POP;
m_Execute[INSTR_ENTER] = ENTER;
m_Execute[INSTR_LEAVE] = LEAVE;
m_Execute[INSTR_CHGSFP] = CHGSFP;
m_Execute[INSTR_RSTSFP] = RSTSFP;
m_Execute[INSTR_NFJP] = NFJP;
}
// destruction code of the machine
CVirtualMachine::~CVirtualMachine()
{
delete m_pbMem;
}
///////////////////////////////////////////////////////////////
// Programmer : Zoly Farkas
// Creation Date : 5/26/99 5:56:44 PM
// Function name : CVirtualMachine::Start
// Description : Virtual Machine execution
// Return type : void
// Argument : int addr
///////////////////////////////////////////////////////////////
REGISTER CVirtualMachine::Start(REGISTER addr, REGISTER sp)
{
m_NI=addr;
m_SP = sp;
m_ST = MS_ACTIVE;
while (m_ST != MS_STOP)
// check the instruction validity
if (m_NI>=0 && m_NI <m_nMemSize)
if (m_pbMem[m_NI]>=0 && m_pbMem[m_NI] < INSTR_NUMBER)
{
(this->*m_Execute[m_pbMem[m_NI]])();
if (m_bTrap)
break;
}
else
{
// Fatal Error unknown instruction
m_ST = MS_ERROR;
break;
}
else break;
return m_ST;
}
// Loads a stack entry from the specified address relative to the frame pointer
// we use this function for variable / parameter operations
void CVirtualMachine::LOD()
{
m_SP += SE_SIZE;
SE(m_SP) = SE(m_FP+SE_SIZE*OFFS(m_NI+VM_ICSIZE));
m_NI += VM_ICSIZE + VM_BYTES;
}
// Loads a stack entry specified directly, we use that for constants
void CVirtualMachine::LODI()
{
m_SP += SE_SIZE;
SE(m_SP) = SE(m_NI+VM_ICSIZE);
m_NI += VM_ICSIZE + SE_SIZE;
}
// Loads a stack entry from the specified address relative to RX register
// I don't know if i will use this instruction
void CVirtualMachine::LODIX()
{
m_SP += SE_SIZE;
SE(m_SP) = SE(SE_SIZE * (OFFS(m_NI+VM_ICSIZE) + m_RX) + m_FP );
m_NI += VM_ICSIZE + VM_BYTES;
}
// Copyes the curent top of stack to the new top of stack
void CVirtualMachine::COPY()
{
m_SP += SE_SIZE;
SE(m_SP) = SE(m_SP - SE_SIZE);
m_NI += VM_ICSIZE;
}
///////////////////////////////////////////////////////////////
// Programmer : Zoly Farkas
// Creation Date : 5/28/99 1:06:38 PM
// Function name : CVirtualMachine::STO
// Description : put's the top of stack value in to the address specified in the
// : second stack entry, pop's the 2 values from the stack
// Return type : void
///////////////////////////////////////////////////////////////
void CVirtualMachine::STO()
{
SE(CV_ADDRESS(SE(m_SP - SE_SIZE).m_Info)) = SE(m_SP);
m_SP -= SE_SIZE*2;
m_NI += VM_ICSIZE;
}
// POP's the stack into the RX register
void CVirtualMachine::MVRX()
{
m_RX = CV_ADDRESS(SE(m_SP).m_Info);
m_SP -= SE_SIZE;
m_NI += VM_ICSIZE;
}
///////////////////////////////////////////////////////////////
// Programmer : Zoly Farkas
// Creation Date : 6/1/99 10:43:42 AM
// Function name : CVirtualMachine::RED
// Description : Cuts a number of elements from the stack
// Return type : void
///////////////////////////////////////////////////////////////
void CVirtualMachine::RED()
{
m_SP -= SE_SIZE * OFFS(m_NI+VM_ICSIZE);
m_NI += VM_ICSIZE+VM_BYTES;
}
// unconditional jump
void CVirtualMachine::UJP()
{
m_NI = AD(m_NI + VM_ICSIZE);
}
// Conditional jump
void CVirtualMachine::FJP()
{
if (CV_BOOLEAN(SE(m_SP).m_Info))
m_NI = AD(m_NI+VM_ICSIZE);
else
m_NI += VM_ICSIZE + VM_BYTES;
m_SP -= SE_SIZE;
}
// less instruction
void CVirtualMachine::LES()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) < SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// Less or equal instruction
void CVirtualMachine::LEQ()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) <= SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// Greater instruction
void CVirtualMachine::GRT()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) > SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// Greater or equal then
void CVirtualMachine::GEQ()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) >= SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// Equal
void CVirtualMachine::EQU()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) == SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// Not Equal
void CVirtualMachine::NEQ()
{
m_SP -= SE_SIZE;
CV_BOOLEAN(SE(m_SP).m_Info) = SE(m_SP) != SE(m_SP + SE_SIZE);
SE(m_SP).m_nType = SE_BOOLEAN;
m_NI += VM_ICSIZE;
}
// The add Instruction
void CVirtualMachine::ADD()
{
m_SP -= SE_SIZE;
if (SE(m_SP).m_nType != SE(m_SP + SE_SIZE).m_nType)
m_ST = MS_ERROR;
else
SE(m_SP) = SE(m_SP) + SE(m_SP + SE_SIZE);
m_NI += VM_ICSIZE;
}
// The substract instruction
void CVirtualMachine::SUB()
{
m_SP -= SE_SIZE;
if (SE(m_SP).m_nType != SE(m_SP + SE_SIZE).m_nType)
m_ST = MS_ERROR;
else
SE(m_SP) = SE(m_SP) - SE(m_SP + SE_SIZE);
m_NI += VM_ICSIZE;
}
// The multiply instruction
void CVirtualMachine::MUL()
{
m_SP -= SE_SIZE;
if (SE(m_SP).m_nType != SE(m_SP + SE_SIZE).m_nType)
m_ST = MS_ERROR;
else
SE(m_SP) = SE(m_SP) * SE(m_SP + SE_SIZE);
m_NI += VM_ICSIZE;
}
// The division Instruction
void CVirtualMachine::DIV()
{
m_SP -= SE_SIZE;
if (SE(m_SP).m_nType != SE(m_SP + SE_SIZE).m_nType)
m_ST = MS_ERROR;
else
SE(m_SP) = SE(m_SP) / SE(m_SP + SE_SIZE);
m_NI += VM_ICSIZE;
}
// The MOD function
void CVirtualMachine::MOD()
{
m_SP -= SE_SIZE;
if (SE(m_SP).m_nType != SE(m_SP + SE_SIZE).m_nType)
// also should check if the two arguments are INT OR CHAR
m_ST = MS_ERROR;
else
SE(m_SP) = SE(m_SP) % SE(m_SP + SE_SIZE);
m_NI += VM_ICSIZE;
}
// Call function
void CVirtualMachine::CALL()
{
m_SP += SE_SIZE;
SE(m_SP).m_nType = SE_ADDRESS;
SE(m_SP).m_Info = m_NI + VM_ICSIZE + VM_BYTES; // Push the returning address to the stack
m_NI = AD(m_NI + 1); // Jump to the routine address
}
// The Ret function
void CVirtualMachine::RET()
{
m_SP -= SE_SIZE;
m_NI = CV_ADDRESS(SE(m_SP+SE_SIZE).m_Info); // jump to the address
}
// Stops the virtual machine
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -