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

📄 vm.cpp

📁 编译并且测试成功的虚拟机
💻 CPP
字号:
#include "stdafx.h"#include "VM.h"#include "Logger.h"#include "Player.h"char *SysFun[] = {"cinit","printf", "getsum"};int global_variable[200];string intToString(int val) {  char *str = new char[255];  sprintf( str, "%i", val);  string res(str);  delete str;  return res;   }VM::VM(char *code, HashMap<string, FUNCTIONHEADER *>* functionList, StackItem *cp) { CS = code; this->functionList = functionList; constantPool = cp;}VM::~VM() { // TODO }/* The core of the VM */void VM::run(ProgramInstance *prog, int maxInstructions) { int instructionsHandled = 0; int pc = 0; int endcode = 0;   while(1) {pc =	 prog->getPC();endcode =  prog->getEndCode(); if (pc >= endcode || prog->dead || prog->sleeping || instructionsHandled > maxInstructions)  	 break;    // Fetch    char opcode = CS[prog->getPC()];  prog->addPC(1);  instructionsHandled++;    // Dispatch:  switch(opcode) {  	case nopC: {  		// Do nothing  	} break;   	case imulC: {  		// Multiply the two top integers on the stack and push the result:  		int v1 = prog->popInt();  		int v2 = prog->popInt();  		prog->pushInt(v1*v2);  	} break;   	case inegC: {  		// negate the top integer  		int v = prog->popInt();  		prog->pushInt(-v);  	} break;   	case iremC: {      // push the modulo of the two top stack items. Notice how we first pop the right-hand value.      // This is how it was encoded in the bytecode.. first it pushes the left value, then the right - so      // the right-hand value is on top of the stack, right!?  	  int v2 = prog->popInt();  	  int v1 = prog->popInt();  	  prog->pushInt(v1%v2);  	} break;   	case isubC: {  		int v2 = prog->popInt();  		int v1 = prog->popInt();  		prog->pushInt(v1-v2);  	} break;   	case idivC: {  		int v2 = prog->popInt();  		int v1 = prog->popInt();  		prog->pushInt(v1/v2);  	} break;   	case iaddC: {  		int v2 = prog->popInt();  		int v1 = prog->popInt();  		prog->pushInt(v1+v2);  	} break;   	case aaddC: {  		string v2 = prog->popStr();  		string v1 = prog->popStr();  		prog->pushStr(v1+v2);  	} break;   	case gotoC: {  		// unconditional jump in the code. Notice how we decode the address directly from the code segment.. that's how  		// we decided to store them in the assembler.  		unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->setPC(address);		} break;   	case ifeqC: {  		// jump if integer on top of stack is equal to zero - otherwise continue.  		// if we should NOT jump we'll have to manually increase the PC to get past the address we just read. It should	    // point to the next instruction after we finish the switch on the current bytecode.	    unsigned int address = *((unsigned int*)&CS[prog->getPC()]);      prog->addPC(sizeof(unsigned int));        if (prog->popInt() == 0) 	      prog->setPC(address);	 } break;   	case ifneC: {  		// jump if top integer is different from zero.      unsigned int address = *((unsigned int*)&CS[prog->getPC()]);      prog->addPC(sizeof(unsigned int));		    if (prog->popInt() != 0) 	      prog->setPC(address);   } break;  	  case if_acmpeqC: { 	    // jump if two topmost strings are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    string v2 = prog->popStr();	    string v1 = prog->popStr();		    if (v1 == v2)	      prog->setPC(address);	  } break; 	  case if_acmpneC: { 	    // jump if two topmost strings are different: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    string v2 = prog->popStr();	    string v1 = prog->popStr();		    if (v1 != v2)	      prog->setPC(address); 	  } break; 	  case if_icmpeqC: { 	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 == v2)	      prog->setPC(address); 	  } break; 	  case if_icmpgtC: { 	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 > v2)	      prog->setPC(address); 	  } break; 	  case if_icmpltC: {	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 < v2)	      prog->setPC(address); 	  } break; 	  case if_icmpleC: {	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 <= v2)	      prog->setPC(address); 	  } break; 	  case if_icmpgeC: { 	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 >= v2)	      prog->setPC(address); 	  } break; 	  case if_icmpneC: {	    // jump if two topmost integers are equal: 	  	unsigned int address = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));	    int v2 = prog->popInt();	    int v1 = prog->popInt();		    if (v1 != v2)	      prog->setPC(address); 	  } break; 	  case ireturnC: { 	  	// Return an integer value to the activation below this one. 	  	 	    // Get the result and arg count: 	    int res = prog->getInt(); 	    int args = prog->getNumParams(); 	  	    //Pop the activation: 	    prog->popActivation(); 	  	    // Pop the arguments in the old activation and push result: 	    prog->pop(args); 	    prog->pushInt(res); 	  } break; 	  case areturnC: { 	  	// Return a string value to the activation below this one. 	  	 	    // Get the result and arg count: 	    string res = prog->getStr(); 	    int args = prog->getNumParams(); 	  	    //Pop the activation: 	    prog->popActivation(); 	  	    // Pop the arguments in the old activation and push result: 	    prog->pop(args); 	    prog->pushStr(res); 	  } break; 	  case returnC: { 	  	// return from a void function to the activation below this one 	  	 	    // Get the arg count: 	    int args = prog->getNumParams(); 	  	    //Pop the activation: 	    prog->popActivation(); 	  	    // Pop the arguments in the old activation: 	    prog->pop(args); 	  } break;    case aloadC: {    	// load a string variable to the top of the stack    	    	// retrieve address of the variable from the code segment (stored as a 16bit integer by assembler)       short unsigned int address = *((short unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(short unsigned int));	    	    // Push the variable to the top of the stack	    prog->pushStr(prog->getLocalStr(address));    } break;    case astoreC: {      // store topmost string to its address in the stack:          	// retrieve address of the variable from the code segment (stored as a 16bit integer by assembler) 	    short unsigned int address = *((short unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(short unsigned int));      	    prog->setLocalStr(prog->popStr(), address);	  } break;	/* add for global variable, chenhongyu, 2004-9-17. */    case iloadC: {    	// retrieve address of the variable from the code segment and increase PC to point at next bytecode	    short unsigned int address = *((short unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(short unsigned int));	    	    // Push the variable to the top of the stack			if (address>=0x1000)		{			prog->pushInt(global_variable[address-0x1000]);		}		else		{			prog->pushInt(prog->getLocalInt(address));		}	        } break;    case istoreC: {      // store topmost string to its address in the stack:	    short unsigned int address = *((short unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(short unsigned int));  		 				if (address>=0x1000)		{			global_variable[address-0x1000] = prog->popInt();		}		else		{			 prog->setLocalInt(prog->popInt(), address);		}	       } break;  	case ldc_intC: {  		// load an integer constant from the constant pool and push it to the stack.  		// index is 32bit unsigned integer (as stored by assembler)  		unsigned int index = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));            prog->pushInt(constantPool[index].intval);  	} break;   	case iconst_0C: {  		// simply push constant 0  		prog->pushInt(0);  	} break;   	case iconst_1C: {      prog->pushInt(1);  	} break;   	case iconst_2C: {      prog->pushInt(2);  	} break;   	case iconst_3C: {      prog->pushInt(3);  	} break;   	case iconst_4C: {      prog->pushInt(4);  	} break;   	case iconst_5C: {      prog->pushInt(5);  	} break;   	case ldc_stringC: {  		// load a string constant from the constant pool and push it to the stack.  		// index is 32bit unsigned integer (as stored by assembler)  		unsigned int index = *((unsigned int*)&CS[prog->getPC()]);	    prog->addPC(sizeof(unsigned int));            prog->pushStr(constantPool[index].strval);  	} break;   	case dupC: {  		// dublicate the top stack item      prog->pushStackItem(prog->getStackItem());  	} break;   	case popC: {  		// pop the top stack item  		prog->pop();  	} break;   	case callC: {      // Call a function:       // Get the index into the constant pool where the name of the function lies as a string: 	    unsigned int index = *((unsigned int*)&CS[prog->getPC()]); 	    prog->addPC(sizeof(unsigned int));      // look up the function in the function hash-table:      FUNCTIONHEADER *theFunction = NULL;      bool found = functionList->get(constantPool[index].strval, &theFunction);            if (found && theFunction != NULL) {      	// Get the current stack pointer for this activation 	      int curSP = prog->getSP(); 	       	      // push a new activation: 	      prog->pushActivation(); 	       	      // Set the start and end byte code for this activation        prog->setPC(theFunction->startCode);        prog->setEC(theFunction->endCode);                // Set the BSP to the first of the arguments to this new activation        prog->setBSP(curSP - theFunction->inputs);                // Set the new stack pointer to BSP + LocalsLimit        prog->setSP(curSP - theFunction->inputs + theFunction->localLimit);                // Save in activation how many input parameters it has (needed to pop it correctly later)         prog->setNumParams(theFunction->inputs);      }      else {		 		 		  if (constantPool[index].strval.compare(SysFun[1]) == 0)		  {			  string abc = prog->popStr();			  Player::instance()->setInt(abc, 2, 0);		  }		  else if (constantPool[index].strval.compare(SysFun[2]) == 0)		  {			  int a = prog->popInt();			  int b = prog->popInt();			  prog->pushInt(a+b);		  }			  else			  {		        // this should never happen.	       Log("ERROR - function %s was not found in VM", constantPool[index].strval.c_str());			  }	    }  	} break;   	case setint_mdlC: {  		// Only the player case of these 'setint' opcodes are 'hooked up' against something in this  		// example VM - but this is where you could plug in your own classes to control integer parameters  		// in them..  		int val = prog->popInt();  		int nr = prog->popInt();  		string name = prog->popStr();      Log("setint called on MDL type - not implemented. Name=%s, nr=%i, val=%i", name.c_str(),nr,val);    } break;   	case setint_particleC: {  		int val = prog->popInt();  		int nr = prog->popInt();  		string name = prog->popStr();      Log("setint called on PARTICLE type - not implemented. Name=%s, nr=%i, val=%i", name.c_str(),nr,val);  	} break;   	case setint_plyC: {  	  int val = prog->popInt();  		int nr = prog->popInt();  		string name = prog->popStr();  		  		// call into the 'engine' to modify some integer parameters in the player object  		Player::instance()->setInt(name,nr,val);  	} break;   	case setint_lightC: {  		int val = prog->popInt();  		int nr = prog->popInt();  		string name = prog->popStr();      Log("setint called on LIGHT type - not implemented. Name=%s, nr=%i, val=%i", name.c_str(),nr,val);   	} break;   	case setint_camC: {  		int val = prog->popInt();  		int nr = prog->popInt();  		string name = prog->popStr();      Log("setint called on CAM type - not implemented. Name=%s, nr=%i, val=%i", name.c_str(),nr,val);   	} break;   	case sleepC: {	    int sleepTime = prog->popInt();	    prog->sleeping = true;	 	  prog->wakeuptime = GetTimeMsec() + sleepTime;  	} break;   	case sleep_trigC: {  		// sleep until triggered again (signalled to the script manager by setting the wakeup time to 0)       prog->sleeping = true;      prog->wakeuptime = 0;		} break;		case cast_booltostringC: {  		// pop a bool of the stack (stored as int), convert it to string and push the result:      int v = prog->popInt();      if (v == 0)       prog->pushStr("false");      else       prog->pushStr("true");    } break;      	case cast_inttostringC: {   		// pop an integer of the stack, convert it to string and push the result:      int v = prog->popInt();      string s = intToString(v);      prog->pushStr(s);  	} break;   	case cast_stringtointC: {  		string s = prog->popStr();  		int v = atoi(s.c_str());  		prog->pushInt(v);  	} break;     default:      Log("Unknown opcode %i", CS[prog->getPC()]);      break;  } // end of switch	 } if (prog->getPC() >= prog->getEndCode()) {   Log("killing program %s  - pc is %i, end of code is %i", prog->getName(), prog->getPC(), prog->getEndCode());   prog->dead = true; }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -