📄 zvm.cpp
字号:
// 读取脚本版本(2字节)
int iMajorVersion = 0;
int iMinorVersion = 0;
fread( &iMajorVersion, 1, 1, pScriptFile );
fread( &iMinorVersion, 1, 1, pScriptFile );
g_iReadSize += 2;
// 验证版本, 当前虚拟机版本支持 v0.0 的脚本
if ( iMajorVersion != 0 || iMinorVersion != 0 )
return LOAD_ERROR_UNSUPPORTED_VERS;
// 读取堆栈大小(4字节)
fread ( &g_Script.Stack.iSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 分配运行时堆栈空间大小
if( g_Script.Stack.iSize == 0 )
g_Script.Stack.iSize = DEF_STACK_SIZE;
g_Script.Stack.pElements = new Value [ g_Script.Stack.iSize ];
memset ( g_Script.Stack.pElements, 0, sizeof(Value) * g_Script.Stack.iSize );
// 读取全局数据大小(4字节)
fread ( &g_Script.iGlobalDataSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 检查 _Main() 是否存在(1字节)
fread ( &g_Script.iIsMainFuncPresent, 1, 1, pScriptFile );
g_iReadSize += 1;
// 读取 _Main() 索引(4字节)
fread ( &g_Script.iMainFuncIndex, 4, 1, pScriptFile );
g_iReadSize += 4;
// ---- 读取指令流
// 读取指令计数(4字节)
fread ( &g_Script.InstrStream.iSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 分配指令流空间
g_Script.InstrStream.pInstrs = new Instr [ g_Script.InstrStream.iSize ];
memset ( g_Script.InstrStream.pInstrs, 0, sizeof(Instr) * g_Script.InstrStream.iSize );
// 读取指令数据
for ( int iCurrInstrIndex = 0;
iCurrInstrIndex < g_Script.InstrStream.iSize;
++ iCurrInstrIndex )
{
// 读取操作码(2字节)
g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCode = 0;
fread( &g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCode, 2, 1, pScriptFile );
g_iReadSize += 2;
// 读取操作数个数(1字节)
g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount = 0;
fread( &g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount, 1, 1, pScriptFile );
g_iReadSize += 1;
int iOpCount = g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount;
// 为操作数列表分配空间
Value *pOpList = new Value [ iOpCount ];
memset ( pOpList, 0, sizeof(Value) * iOpCount );
// 读取操作数列表(N字节)
for ( int iCurrOpIndex = 0;
iCurrOpIndex < iOpCount;
++ iCurrOpIndex )
{
// 把当前操作数赋值给引用 CurrOp, 方便后续编码
Value &CurrOp = pOpList [ iCurrOpIndex ];
// 读取操作数类型(1字节)
CurrOp.iType = 0;
fread ( &CurrOp.iType, 1, 1, pScriptFile );
g_iReadSize += 1;
// 根据操作数类型,读取操作数数据
switch ( CurrOp.iType )
{
// int 字面量
case OP_TYPE_INT:
{
fread ( &CurrOp.iIntLiteral, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// float 字面量
case OP_TYPE_FLOAT:
{
fread ( &CurrOp.fFloatLiteral, sizeof(float), 1, pScriptFile );
g_iReadSize += sizeof(float);
break;
}
// 字符串索引
case OP_TYPE_STRING:
{
// 字符串索引存储在 int 字面值字段中
fread ( &CurrOp.iIntLiteral, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// 指令索引
case OP_TYPE_INSTR_INDEX:
{
fread ( &CurrOp.iInstrIndex, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// 绝对堆栈索引
case OP_TYPE_ABS_STACK_INDEX:
{
fread ( &CurrOp.iStackIndex, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// 相对堆栈索引
case OP_TYPE_REL_STACK_INDEX:
{
fread ( &CurrOp.iStackIndex, sizeof(int), 1, pScriptFile );
fread ( &CurrOp.iOffsetIndex, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int)*2;
break;
}
// 函数索引
case OP_TYPE_FUNC_INDEX:
{
fread ( &CurrOp.iFuncIndex, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// 主程序 API 调用索引
case OP_TYPE_HOST_API_CALL_INDEX:
{
fread ( &CurrOp.iHostAPICallIndex, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
// 寄存器
case OP_TYPE_REG:
{
fread ( &CurrOp.iReg, sizeof(int), 1, pScriptFile );
g_iReadSize += sizeof(int);
break;
}
} // end switch
} // end for
// 为操作数列表指针赋值
g_Script.InstrStream.pInstrs [ iCurrInstrIndex ].pOpList = pOpList;
} // end for
// ---- 读取字符串表
// 读取字符串表大小(4字节)
int iStringTableSize = 0;
fread ( &iStringTableSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 如果字符串表不为空,读取它
if( iStringTableSize != 0 )
{
// 为临时字符串表分配空间
char **ppstrStringTable = new char* [ iStringTableSize ];
// 读取每个字符串
for ( int iCurrStringIndex = 0;
iCurrStringIndex < iStringTableSize;
++ iCurrStringIndex )
{
// 读取字符串大小(4字节)
int iStringSize;
fread ( &iStringSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 为字符串分配空间
char *pstrCurrString = new char [ iStringSize + 1 ];
// 读取字符串(N字节)
fread( pstrCurrString, iStringSize, 1, pScriptFile );
pstrCurrString [ iStringSize ] = '\0';
// 把字符串指针赋给字符串表
ppstrStringTable [ iCurrStringIndex ] = pstrCurrString;
}
// 遍历指令流中每个指令的所有操作数,
// 检测字符串类型,为字符串字面值赋值
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 )
{
// 取得当前操作数的引用,方便后续编码
Value &CurrOp = pOpList [ iCurrOpIndex ];
// 检测操作数类型是否是字符串
if( CurrOp.iType == OP_TYPE_STRING )
{
// 取得当前字符串在字符串表中的索引
// 此索引存储在 iIntLiteral 字段中
int iStringIndex = CurrOp.iIntLiteral;
// 计算字符串大小
size_t iStringSize = strlen ( ppstrStringTable [ iStringIndex ] );
// 为当前操作数字符串字面值字段分配空间
CurrOp.pstrStringLiteral = new char [ iStringSize + 1 ];
// 拷贝字符串
strcpy_s( CurrOp.pstrStringLiteral, iStringSize+1, ppstrStringTable [ iStringIndex ] );
}
}
}
// 释放临时字符串表中的字符串
for ( int iCurrStringIndex = 0;
iCurrStringIndex < iStringTableSize;
++ iCurrStringIndex )
{
delete ppstrStringTable [ iCurrStringIndex ];
}
// 释放临时字符串表本身
delete ppstrStringTable;
} // end if
// ---- 读取函数表
// 读取函数表大小(4字节)
int iFuncTableSize = 0;
fread ( &iFuncTableSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 为函数表分配空间
g_Script.pFuncTable = new Func [ iFuncTableSize ];
// 读取各个函数
for ( int iCurrFuncIndex = 0;
iCurrFuncIndex < iFuncTableSize;
++ iCurrFuncIndex )
{
// 读取入口点(4字节)
int iEntryPoint;
fread ( &iEntryPoint, 4, 1, pScriptFile );
g_iReadSize += 4;
// 读取参数个数(1字节)
int iParamCount = 0;
fread ( &iParamCount, 1, 1, pScriptFile );
g_iReadSize += 1;
// 读取局部数据大小(4字节)
int iLocalDataSize;
fread ( &iLocalDataSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 计算堆栈框架大小
int iStackFrameSize = iParamCount + 1 + iLocalDataSize;
// 把信息写入函数表
g_Script.pFuncTable [ iCurrFuncIndex ].iEntryPoint = iEntryPoint;
g_Script.pFuncTable [ iCurrFuncIndex ].iLocalDataSize = iLocalDataSize;
g_Script.pFuncTable [ iCurrFuncIndex ].iParamCount = iParamCount;
g_Script.pFuncTable [ iCurrFuncIndex ].iStackFrameSize = iStackFrameSize;
}
// ---- 读取主程序 API 调用表
// 读取主程序 API 调用表大小(4字节)
fread ( &g_Script.HostAPICallTable.iSize, 4, 1, pScriptFile );
g_iReadSize += 4;
// 为调用表分配空间
g_Script.HostAPICallTable.ppstrCalls = new char* [ g_Script.HostAPICallTable.iSize ];
// 读取各个函数名
for ( int iCurrCallIndex = 0;
iCurrCallIndex < g_Script.HostAPICallTable.iSize;
++ iCurrCallIndex )
{
// 读取函数名长度
int iCallLength = 0;
fread ( &iCallLength, 4, 1, pScriptFile );
g_iReadSize += 4;
// 为函数名分配空间到临时指针
char *pstrCurrCall = new char [ iCallLength + 1 ];
// 读取函数名
fread ( pstrCurrCall, iCallLength, 1, pScriptFile );
g_iReadSize += iCallLength;
pstrCurrCall [ iCallLength ] = '\0';
// 将临时指针赋值给API调用表
g_Script.HostAPICallTable.ppstrCalls [ iCurrCallIndex ] = pstrCurrCall;
}
// ---- 关闭文件
fclose( pScriptFile );
// ---- 打印装载信息
printf ( "%s 加载成功!\n", pstrFileName );
printf ( "\n" );
printf ( "脚本版本: v%d.%d\n", iMajorVersion, iMinorVersion );
printf ( "堆栈大小: %d\n", g_Script.Stack.iSize );
printf ( "全局数据大小:%d\n", g_Script.iGlobalDataSize );
printf ( "字符串表大小:%d\n", iStringTableSize );
printf ( "函数总数: %d\n", iFuncTableSize );
printf ( "读取字节总数:%d\n", g_iReadSize );
printf ( "\n" );
printf ( "_Main() 是否出现:" );
if( g_Script.iIsMainFuncPresent )
printf ( "是, 索引(%d)\n", g_Script.iMainFuncIndex );
else
printf ( "否\n" );
printf ( "\n" );
printf ( "主程序API调用总数: %d", g_Script.HostAPICallTable.iSize );
printf ( "\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -