📄 zvm.cpp
字号:
/*
文件:
ZVM.cpp
内容:
执行 .ZSE 可执行文件的虚拟机的实现
作者:
张锦
日期:
01.05.2009
版本:
v 1.0
*/
// ---- 包含文件 ----------------------------------------------------------------------------------
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <windows.h>
using namespace std;
// ---- 全局常量 ----------------------------------------------------------------------------------
// ---- 文件 ----------------------------------------------------------------------------------
#define EXEC_FILE_EXT ".ZSE" // 可执行文件扩展名
#define ZSE_ID_STRING "ZSE0" // .ZSE 文件标识
// ---- LoadScript() 错误码 -------------------------------------------------------------------
#define LOAD_OK 0 // 加载成功
#define LOAD_ERROR_FILE_IO 1 // 打开文件失败
#define LOAD_ERROR_INVALID_ZSE 2 // 文件类型不正确
#define LOAD_ERROR_UNSUPPORTED_VERS 4 // 版本不正确
// ---- 操作数类型 ----------------------------------------------------------------------------
#define OP_TYPE_NULL -1 // 未初始化的操作数 / NULL
#define OP_TYPE_INT 0 // int型 字面量
#define OP_TYPE_FLOAT 1 // float型 字面量
#define OP_TYPE_STRING 2 // 字符串
#define OP_TYPE_ABS_STACK_INDEX 3 // 绝对堆栈索引
#define OP_TYPE_REL_STACK_INDEX 4 // 相对堆栈索引
#define OP_TYPE_INSTR_INDEX 5 // 指令索引
#define OP_TYPE_FUNC_INDEX 6 // 函数索引
#define OP_TYPE_HOST_API_CALL_INDEX 7 // 主程序 API 调用索引
#define OP_TYPE_REG 8 // 寄存器
// ---- 指令操作码 --------------------------------------------------------------------------------
#define INSTR_MOV 0
#define INSTR_ADD 1
#define INSTR_SUB 2
#define INSTR_MUL 3
#define INSTR_DIV 4
#define INSTR_MOD 5
#define INSTR_EXP 6
#define INSTR_NEG 7
#define INSTR_INC 8
#define INSTR_DEC 9
#define INSTR_AND 10
#define INSTR_OR 11
#define INSTR_XOR 12
#define INSTR_NOT 13
#define INSTR_SHL 14
#define INSTR_SHR 15
#define INSTR_CONCAT 16
#define INSTR_GETCHAR 17
#define INSTR_SETCHAR 18
#define INSTR_JMP 19
#define INSTR_JE 20
#define INSTR_JNE 21
#define INSTR_JG 22
#define INSTR_JL 23
#define INSTR_JGE 24
#define INSTR_JLE 25
#define INSTR_PUSH 26
#define INSTR_POP 27
#define INSTR_CALL 28
#define INSTR_RET 29
#define INSTR_CALLHOST 30
#define INSTR_PAUSE 31
#define INSTR_EXIT 32
// ---- 堆栈 ----------------------------------------------------------------------------------
#define DEF_STACK_SIZE 1024 // 堆栈默认大小
// ---- 强制转换 ------------------------------------------------------------------------------
#define MAX_COERCION_STRING_SIZE 65 // 允许强制转换成字符串的最大字符串长度
// ---- 数据结构 ----------------------------------------------------------------------------------
// ---- 运行时值 ------------------------------------------------------------------------------
struct Value
{
int iType; // 类型
union
{
int iIntLiteral; // 整形字面量
float fFloatLiteral; // 浮点型字面量
char *pstrStringLiteral; // 字符串表索引
int iStackIndex; // 堆栈索引
int iInstrIndex; // 指令索引
int iFuncIndex; // 函数索引
int iHostAPICallIndex; // 主应用程序API调用索引
int iReg; // 寄存器码
};
int iOffsetIndex; // 偏移量索引
};
// ---- 运行时堆栈 ----------------------------------------------------------------------------
struct RuntimeStack
{
Value *pElements; // 堆栈元素
int iSize; // 堆栈元素个数
int iTopIndex; // 栈顶索引
int iFrameIndex; // 当前堆栈框架顶部索引
};
// ---- 指令 ----------------------------------------------------------------------------------
struct Instr // 指令
{
int iOpCode; // 指令操作码
int iOpCount; // 操作数个数
Value *pOpList; // 操作数列表
};
struct InstrStream
{
Instr *pInstrs; // 指令本身
int iSize; // 指令流中指令条数
int iCurrInstr; // 当前指令
};
// ---- 函数 ----------------------------------------------------------------------------------
struct Func
{
int iEntryPoint; // 函数入口点
int iParamCount; // 参数个数
int iLocalDataSize; // 局部数据大小
int iStackFrameSize;// 堆栈框架的总的小
};
// ---- 主程序API调用 -------------------------------------------------------------------------
struct HostAPICallTable
{
char **ppstrCalls; // 指向函数名数组的指针
int iSize; // 数组中函数名的个数
};
// ---- 脚本 ----------------------------------------------------------------------------------
struct Script
{
// 头数据
int iGlobalDataSize; // 脚本全局数据大小
// 数据
int iIsMainFuncPresent; // _Main() 是否存在
int iMainFuncIndex; // _Main() 的索引
int iIsPaused; // 是否被暂停
int iPauseEndTime; // 如果暂停,什么时候继续
// 寄存器
Value _RetVal; // _RetVal 寄存器
// 脚本数据
InstrStream InstrStream; // 指令流
RuntimeStack Stack; // 运行时堆栈
Func* pFuncTable; // 函数表
HostAPICallTable HostAPICallTable; // 主程序API调用表
};
// ---- 全局变量 ----------------------------------------------------------------------------------
// ---- 脚本 ----------------------------------------------------------------------------------
Script g_Script; // 全局脚本实例
// ---- 指令助记符 ----------------------------------------------------------------------------
char ppstrMnemonics [][12] =
{
"Mov",
"Add", "Sub", "Mul", "Div", "Mod", "Exp", "Neg", "Inc", "Dec",
"And", "Or", "Xor", "Not", "SHL", "SHR",
"Concat", "GetChar", "SetChar",
"Jmp", "JE", "JNE", "JG", "JL", "JGE", "JLE",
"Push", "Pop",
"Call", "Ret", "CallHost",
"Pause", "Exit"
};
// ---- 读取字节数 ----------------------------------------------------------------------------
size_t g_iReadSize = 0;
// ---- 函数原型 ----------------------------------------------------------------------------------
// ---- 主函数 --------------------------------------------------------------------------------
void Init ();
void ShutDown ();
// ---- 脚本接口 ------------------------------------------------------------------------------
int LoadScript ( char *pstrFileName );
void RunScript ();
void ResetScript ();
// ---- 操作数接口 ----------------------------------------------------------------------------
int CoerceValueToInt ( Value &val );
float CoerceValueToFloat ( Value &val );
char* CoerceValueToString ( Value &val );
void CopyValue ( Value* pDest, Value &Source );
int GetOpType ( int iOpIndex );
int ResolveStackIndex ( int iIndex );
int ResolveOpStackIndex ( int iOpIndex );
Value ResolveOpValue ( int iOpIndex );
int ResolveOpType ( int iOpIndex );
int ResolveOpAsInt ( int iOpIndex );
float ResolveOpAsFloat ( int iOpIndex );
char* ResolveOpAsString ( int iOpIndex );
int ResolveOpAsInstrIndex ( int iOpIndex );
int ResolveOpAsFuncIndex ( int iOpIndex );
char* ResolveOpAsHostAPICall ( int iOpIndex );
Value* ResolveOpPntr ( int iOpIndex );
// ---- 运行时堆栈接口 ------------------------------------------------------------------------
Value GetStackValue ( int iIndex );
void SetStackValue ( int iIndex, Value val );
void Push ( Value val );
Value Pop ();
void PushFrame ( int iSize );
void PopFrame ( int iSize );
// ---- 函数表接口 ----------------------------------------------------------------------------
Func GetFunc ( int iIndex );
// ---- 主程序 API 调用接口 -------------------------------------------------------------------
char* GetHostAPICall ( int iIndex );
// ---- 打印帮助信息 --------------------------------------------------------------------------
void PrintOpIndir ( int iOpIndex );
void PrintOpValue ( int iOpIndex );
// ---- 时间函数 ------------------------------------------------------------------------------
int GetCurrTime();
// ---- 函数实现 ----------------------------------------------------------------------------------
/**********************************************************************************************
*
* Init ()
*
* 初始化脚本系统
*/
void Init ()
{
// 初始化脚本结构
memset ( &g_Script, 0, sizeof(Script) );
}
/**********************************************************************************************
*
* ShutDown ()
*
* 关闭脚本系统
*/
void ShutDown ()
{
// ---- 释放指令流
// 释放指令流元素
for ( int iCurrInstrIndex = 0;
iCurrInstrIndex < g_Script.InstrStream.iSize;
++ iCurrInstrIndex )
{
int iOpCount = g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount;
Value *pOpList = g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].pOpList;
for( int iCurrOpIndex = 0;
iCurrOpIndex < iOpCount;
++ iCurrOpIndex )
{
if ( pOpList [ iCurrOpIndex ].pstrStringLiteral != 0 &&
pOpList [ iCurrOpIndex ].iType == OP_TYPE_STRING )
delete pOpList [ iCurrOpIndex ].pstrStringLiteral;
}
}
// 释放指令流本身
delete g_Script.InstrStream.pInstrs;
// ---- 释放运行时堆栈
// 释放堆栈元素
for ( int iCurrElmntIndex = 0;
iCurrElmntIndex < g_Script.Stack.iSize;
++ iCurrElmntIndex )
{
if ( g_Script.Stack.pElements [ iCurrElmntIndex ].pstrStringLiteral != 0 &&
g_Script.Stack.pElements [ iCurrElmntIndex ].iType == OP_TYPE_STRING )
delete g_Script.Stack.pElements [ iCurrElmntIndex ].pstrStringLiteral;
}
// 释放堆栈本身
delete g_Script.Stack.pElements;
// ---- 释放函数表
if ( g_Script.pFuncTable )
delete g_Script.pFuncTable;
// ---- 释放主程序 API 调用表
// 释放调用表中各个字符串
for ( int iCurrCallIndex = 0;
iCurrCallIndex < g_Script.HostAPICallTable.iSize;
++ iCurrCallIndex )
{
if( g_Script.HostAPICallTable.ppstrCalls [ iCurrCallIndex ] != 0 )
delete g_Script.HostAPICallTable.ppstrCalls [ iCurrCallIndex ];
}
// 释放调用表本身
if( g_Script.HostAPICallTable.ppstrCalls != 0 )
delete g_Script.HostAPICallTable.ppstrCalls;
}
/**********************************************************************************************
*
* LoadScript ()
*
* 装载脚本
*/
int LoadScript ( char *pstrFileName )
{
// ---- 打开文件
FILE * pScriptFile;
fopen_s( &pScriptFile, pstrFileName, "rb" );
if ( !pScriptFile )
return LOAD_ERROR_FILE_IO;
// ---- 读取.zse文件头
// 读取 ID 字符串(4字节)
char *pstrIDString = new char[5];
fread( pstrIDString, 4, 1, pScriptFile );
pstrIDString [ strlen ( ZSE_ID_STRING ) ] = '\0';
g_iReadSize += 4;
// 检测 ID 字符串
if( strcmp ( pstrIDString, ZSE_ID_STRING ) != 0 )
return LOAD_ERROR_INVALID_ZSE;
delete pstrIDString;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -