⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 virtualmachine.cpp

📁 袖珍型的pascal编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -