📄 rarvm.cpp
字号:
case VM_PUSH: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],GET_VALUE(false,Op1)); break; case VM_POP: SET_VALUE(false,Op1,GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; break; case VM_CALL: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1); SET_IP(GET_VALUE(false,Op1)); continue; case VM_NOT: SET_VALUE(Cmd->ByteMode,Op1,~GET_VALUE(Cmd->ByteMode,Op1)); break; case VM_SHL: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1<<Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1<<(Value2-1))&0x80000000 ? VM_FC:0); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SHR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SAR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(((int)Value1)>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_NEG: { uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1)); Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#ifdef VM_OPTIMIZE case VM_NEGB: SET_VALUE(true,Op1,-GET_VALUE(true,Op1)); break; case VM_NEGD: SET_VALUE(false,Op1,-GET_VALUE(false,Op1)); break;#endif case VM_PUSHA: { const int RegCount=sizeof(R)/sizeof(R[0]); for (int I=0,SP=R[7]-4;I<RegCount;I++,SP-=4) SET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK],R[I]); R[7]-=RegCount*4; } break; case VM_POPA: { const int RegCount=sizeof(R)/sizeof(R[0]); for (uint I=0,SP=R[7];I<RegCount;I++,SP+=4) R[7-I]=GET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK]); } break; case VM_PUSHF: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Flags); break; case VM_POPF: Flags=GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK]); R[7]+=4; break; case VM_MOVZX: SET_VALUE(false,Op1,GET_VALUE(true,Op2)); break; case VM_MOVSX: SET_VALUE(false,Op1,(signed char)GET_VALUE(true,Op2)); break; case VM_XCHG: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); SET_VALUE(Cmd->ByteMode,Op2,Value1); } break; case VM_MUL: { uint Result=GET_VALUE(Cmd->ByteMode,Op1)*GET_VALUE(Cmd->ByteMode,Op2); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_DIV: { uint Divider=GET_VALUE(Cmd->ByteMode,Op2); if (Divider!=0) { uint Result=GET_VALUE(Cmd->ByteMode,Op1)/Divider; SET_VALUE(Cmd->ByteMode,Op1,Result); } } break; case VM_ADC: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC); if (Cmd->ByteMode) Result&=0xff; Flags=(Result<Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS)); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SBB: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC); if (Cmd->ByteMode) Result&=0xff; Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS)); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#endif // for #ifndef NORARVM case VM_RET: if (R[7]>=VM_MEMSIZE) return(true); SET_IP(GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; continue;#ifdef VM_STANDARDFILTERS case VM_STANDARD: ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data); break;#endif case VM_PRINT: break; } Cmd++; --MaxOpCount; }}void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg){ InitBitInput(); memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE)); // Calculate the single byte XOR checksum to check validity of VM code. byte XorSum=0; for (int I=1;I<CodeSize;I++) XorSum^=Code[I]; faddbits(8); Prg->CmdCount=0; if (XorSum==Code[0]) // VM code is valid if equal. {#ifdef VM_STANDARDFILTERS VM_StandardFilters FilterType=IsStandardFilter(Code,CodeSize); if (FilterType!=VMSF_NONE) { // VM code is found among standard filters. Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; CurCmd->OpCode=VM_STANDARD; CurCmd->Op1.Data=FilterType; CurCmd->Op1.Addr=&CurCmd->Op1.Data; CurCmd->Op2.Addr=&CurCmd->Op2.Data; CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; CodeSize=0; }#endif uint DataFlag=fgetbits(); faddbits(1); // Read static data contained in DB operators. This data cannot be // changed, it is a part of VM code, not a filter parameter. if (DataFlag&0x8000) { int DataSize=ReadData(*this)+1; for (int I=0;InAddr<CodeSize && I<DataSize;I++) { Prg->StaticData.Add(1); Prg->StaticData[I]=fgetbits()>>8; faddbits(8); } } while (InAddr<CodeSize) { Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount]; uint Data=fgetbits(); if ((Data&0x8000)==0) { CurCmd->OpCode=(VM_Commands)(Data>>12); faddbits(4); } else { CurCmd->OpCode=(VM_Commands)((Data>>10)-24); faddbits(6); } if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE) { CurCmd->ByteMode=fgetbits()>>15; faddbits(1); } else CurCmd->ByteMode=0; CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; int OpNum=(VM_CmdFlags[CurCmd->OpCode] & VMCF_OPMASK); CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL; if (OpNum>0) { DecodeArg(CurCmd->Op1,CurCmd->ByteMode); // reading the first operand if (OpNum==2) DecodeArg(CurCmd->Op2,CurCmd->ByteMode); // reading the second operand else { if (CurCmd->Op1.Type==VM_OPINT && (VM_CmdFlags[CurCmd->OpCode]&(VMCF_JUMP|VMCF_PROC))) { // Calculating jump distance. int Distance=CurCmd->Op1.Data; if (Distance>=256) Distance-=256; else { if (Distance>=136) Distance-=264; else if (Distance>=16) Distance-=8; else if (Distance>=8) Distance-=16; Distance+=Prg->CmdCount; } CurCmd->Op1.Data=Distance; } } } Prg->CmdCount++; } } // Adding RET command at the end of program. Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; CurCmd->OpCode=VM_RET; CurCmd->Op1.Addr=&CurCmd->Op1.Data; CurCmd->Op2.Addr=&CurCmd->Op2.Data; CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; // If operand 'Addr' field has not been set by DecodeArg calls above, // let's set it to point to operand 'Data' field. It is necessary for // VM_OPINT type operands (usual integers) or maybe if something was // not set properly for other operands. 'Addr' field is required // for quicker addressing of operand data. for (int I=0;I<Prg->CmdCount;I++) { VM_PreparedCommand *Cmd=&Prg->Cmd[I]; if (Cmd->Op1.Addr==NULL) Cmd->Op1.Addr=&Cmd->Op1.Data; if (Cmd->Op2.Addr==NULL) Cmd->Op2.Addr=&Cmd->Op2.Data; }#ifdef VM_OPTIMIZE if (CodeSize!=0) Optimize(Prg);#endif}void RarVM::DecodeArg(VM_PreparedOperand &Op,bool ByteMode){ uint Data=fgetbits(); if (Data & 0x8000) { Op.Type=VM_OPREG; // Operand is register (R[0]..R[7]) Op.Data=(Data>>12)&7; // Register number Op.Addr=&R[Op.Data]; // Register address faddbits(4); // 1 flag bit and 3 register number bits } else if ((Data & 0xc000)==0) { Op.Type=VM_OPINT; // Operand is integer if (ByteMode) { Op.Data=(Data>>6) & 0xff; // Byte integer. faddbits(10); } else { faddbits(2); Op.Data=ReadData(*this); // 32 bit integer. } } else { // Operand is data addressed by register data, base address or both. Op.Type=VM_OPREGMEM; if ((Data & 0x2000)==0) { // Base address is zero, just use the address from register. Op.Data=(Data>>10)&7; Op.Addr=&R[Op.Data]; Op.Base=0; faddbits(6); } else { if ((Data & 0x1000)==0) { // Use both register and base address. Op.Data=(Data>>9)&7; Op.Addr=&R[Op.Data]; faddbits(7); } else { // Use base address only. Access memory by fixed address. Op.Data=0; faddbits(4); } Op.Base=ReadData(*this); // Read base address. } }}uint RarVM::ReadData(BitInput &Inp){ uint Data=Inp.fgetbits(); switch(Data&0xc000) { case 0: Inp.faddbits(6); return((Data>>10)&0xf); case 0x4000: if ((Data&0x3c00)==0) { Data=0xffffff00|((Data>>2)&0xff); Inp.faddbits(14); } else { Data=(Data>>6)&0xff; Inp.faddbits(10); } return(Data); case 0x8000: Inp.faddbits(2); Data=Inp.fgetbits(); Inp.faddbits(16); return(Data); default: Inp.faddbits(2); Data=(Inp.fgetbits()<<16); Inp.faddbits(16); Data|=Inp.fgetbits(); Inp.faddbits(16); return(Data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -