📄 zvm.cpp
字号:
// 打印操作信息
PrintOpIndir ( 0 );
printf ( ", " );
PrintOpValue ( 1 );
break;
}
case INSTR_GETCHAR:
{
// 局部赋值目的操作数
Value Dest = ResolveOpValue ( 0 );
// 局部复制源操作数字符串
char *pstrSourceString = ResolveOpAsString ( 1 );
// 检测目的操作数是否已经是字符串
char *pstrNewString;
if ( Dest.iType == OP_TYPE_STRING )
{
// 目的操作数是字符串,确保字符串空间大于二
if ( strlen ( Dest.pstrStringLiteral ) >= 1 )
{
pstrNewString = Dest.pstrStringLiteral;
}
else
{
delete Dest.pstrStringLiteral;
pstrNewString = new char [ 2 ];
}
}
else
{
// 目的操作数不是字符串,更改操作数类型为字符串类型,
// 并为新字符串分配2字节空间
Dest.iType = OP_TYPE_STRING;
pstrNewString = new char [ 2 ];
}
// 取得索引
int iSourceIndex = ResolveOpAsInt ( 2 );
// 从源串索引位置取得字符
pstrNewString [ 0 ] = pstrSourceString [ iSourceIndex ];
pstrNewString [ 1 ] = '\0';
// 将新串写入到 临时复制的目的操作数中
Dest.pstrStringLiteral = pstrNewString;
// 将Dest写回目的操作数
*ResolveOpPntr ( 0 ) = Dest;
// 打印操作信息
PrintOpIndir ( 0 );
printf ( ", " );
PrintOpValue ( 1 );
printf ( ", " );
PrintOpValue ( 2 );
break;
}
case INSTR_SETCHAR:
{
// 检测目的操作数是否是字符串
if ( ResolveOpType ( 0 ) != OP_TYPE_STRING )
{
break;
}
// 取得索引
int iDestIndex = ResolveOpAsInt ( 1 );
// 取得包含要设置字符的字符串
char *pstrSourceString = ResolveOpAsString ( 2 );
// 更新目的操作数索引位置的字符
ResolveOpPntr ( 0 ) ->pstrStringLiteral [ iDestIndex ] = pstrSourceString [ 0 ];
// 打印操作信息
PrintOpIndir ( 0 );
printf ( ", " );
PrintOpValue ( 1 );
printf ( ", " );
PrintOpValue ( 2 );
break;
}
// ---- 跳转指令
case INSTR_JMP:
{
// 取得目标指令索引
int iTargetIndex = ResolveOpAsInstrIndex ( 0 );
// 更改指令技术到目标指令
g_Script.InstrStream.iCurrInstr = iTargetIndex;
// 打印操作信息
PrintOpValue ( 0 );
break;
}
case INSTR_JE:
case INSTR_JNE:
case INSTR_JG:
case INSTR_JL:
case INSTR_JGE:
case INSTR_JLE:
{
// 取得两个操作数
Value op0 = ResolveOpValue ( 0 );
Value op1 = ResolveOpValue ( 1 );
// 取得目标指令索引 (保存在操作数2中)
int iTargetIndex = ResolveOpAsInstrIndex ( 2 );
// 根据不同指令,决定是否跳转
bool bJump = false;
switch ( iOpCode )
{
// je
case INSTR_JE:
switch ( op0.iType )
{
case OP_TYPE_INT:
if ( op0.iIntLiteral == op1.iIntLiteral )
{
bJump = true;
}
break;
case OP_TYPE_FLOAT:
if ( op0.fFloatLiteral == op1.fFloatLiteral )
{
bJump = true;
}
break;
case OP_TYPE_STRING:
if ( strcmp ( op0.pstrStringLiteral, op1.pstrStringLiteral ) == 0 )
{
bJump = true;
}
break;
}
break;
// jne
case INSTR_JNE:
switch ( op0.iType )
{
case OP_TYPE_INT:
if ( op0.iIntLiteral != op1.iIntLiteral )
{
bJump = true;
}
break;
case OP_TYPE_FLOAT:
if ( op0.fFloatLiteral != op1.fFloatLiteral )
{
bJump = true;
}
break;
case OP_TYPE_STRING:
if ( strcmp ( op0.pstrStringLiteral, op1.pstrStringLiteral ) != 0 )
{
bJump = true;
}
break;
}
break;
// jg
case INSTR_JG:
if ( op0.iType == OP_TYPE_INT )
{
if ( op0.iIntLiteral > op1.iIntLiteral )
{
bJump = true;
}
}
else
{
if ( op0.fFloatLiteral > op1.fFloatLiteral )
{
bJump = true;
}
}
break;
// jl
case INSTR_JL:
if ( op0.iType == OP_TYPE_INT )
{
if ( op0.iIntLiteral < op1.iIntLiteral )
{
bJump = true;
}
}
else
{
if ( op0.fFloatLiteral < op1.fFloatLiteral )
{
bJump = true;
}
}
break;
// jge
case INSTR_JGE:
if ( op0.iType == OP_TYPE_INT )
{
if ( op0.iIntLiteral >= op1.iIntLiteral )
{
bJump = true;
}
}
else
{
if ( op0.fFloatLiteral >= op1.fFloatLiteral )
{
bJump = true;
}
}
break;
// jle
case INSTR_JLE:
if ( op0.iType == OP_TYPE_INT )
{
if ( op0.iIntLiteral <= op1.iIntLiteral )
{
bJump = true;
}
}
else
{
if ( op0.fFloatLiteral <= op1.fFloatLiteral )
{
bJump = true;
}
}
break;
}
// 打印操作信息
PrintOpValue ( 0 );
printf ( ", " );
PrintOpValue ( 1 );
printf ( ", " );
PrintOpValue ( 2 );
printf ( " " );
// 检测 bJump 标志,决定是否跳转
if ( bJump == true )
{
g_Script.InstrStream.iCurrInstr = iTargetIndex;
printf ( "true" );
}
else
{
printf ( "false" );
}
break;
}
// ---- 堆栈操作指令
case INSTR_PUSH:
{
// 局部赋值目的操作数
Value Source = ResolveOpValue ( 0 );
// 压栈
Push ( Source );
// 打印操作信息
PrintOpValue ( 0 );
break;
}
case INSTR_POP:
{
// 弹出值并存入目的操作数
*ResolveOpPntr ( 0 ) = Pop();
// 打印操作信息
PrintOpValue ( 0 );
break;
}
// ---- 函数调用
case INSTR_CALL:
{
// 从目的操作数取得函数索引并进而取得函数节点
int iFuncIndex = ResolveOpAsFuncIndex ( 0 );
Func Dest = GetFunc ( iFuncIndex );
// 取得 call 指令之后一条指令的索引,即返回地址,并压栈
Value ReturnAddr;
ReturnAddr.iInstrIndex = g_Script.InstrStream.iCurrInstr + 1;
Push ( ReturnAddr );
// 压入堆栈框架 + 1的空间 (额外的一个空间是给函数索引的,函数索引紧跟在在堆栈框架之后)
PushFrame ( Dest.iLocalDataSize + 1 );
// 写函数索引以及先前堆栈框架索引
Value FuncIndex;
FuncIndex.iFuncIndex = iFuncIndex;
FuncIndex.iOffsetIndex = g_Script.Stack.iFrameIndex; // 先前堆栈框架索引存储在 iOffsetIndex 中
SetStackValue ( g_Script.Stack.iTopIndex - 1, FuncIndex );
// 跳转到函数入口
g_Script.InstrStream.iCurrInstr = Dest.iEntryPoint;
printf ( " $$[ %d ]$$", g_Script.InstrStream.iCurrInstr );
// 打印一些信息
printf ( "%d ( Entry Point: %d, Frame Size: %d )", iFuncIndex, Dest.iEntryPoint, Dest.iStackFrameSize );
break;
}
case INSTR_RET:
{
// 弹出函数索引
Value FuncIndex = Pop ();
Func CurrFunc = GetFunc ( FuncIndex.iFuncIndex );
int iFrameIndex = FuncIndex.iOffsetIndex;
// 取得返回地址
Value ReturnAddr = GetStackValue ( g_Script.Stack.iTopIndex - CurrFunc.iLocalDataSize - 1 );
// 弹出堆栈框架
PopFrame ( CurrFunc.iStackFrameSize );
// 存储先前的堆栈索引
g_Script.Stack.iFrameIndex = iFrameIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -