📄 bombillacore.nc
字号:
if (arg->value.var >= BOMB_HEAPSIZE || arg->value.var < 0) { call BombillaError.error(context, BOMB_ERROR_INVALID_LOCK); return; } dbg_clear(DBG_USR1, " %i\n", (int)arg->value.var); context->releaseSet |= (1 << arg->value.var); break; case OPpunlockb: dbg(DBG_USR1, "VM (%i): Releasing locks", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} if ((arg->value.var & context->heldSet) != arg->value.var) { call BombillaError.error(context, BOMB_ERROR_UNLOCK_INVALID); return; } dbg_clear(DBG_USR1, " 0x%hx\n", arg->value.var); context->releaseSet |= arg->value.var; break; case OPlogwl: case OPlogr: dbg(DBG_ERROR, "VM (%i): Unimplemented class 2 instruction: 0x%hhx.\n", (int)context->which, instr); break; case OPbget: { BombillaStackVariable element; BombillaStackVariable* arg2 = call Stacks.popOperand(context); dbg(DBG_USR1, "Getting element from buffer\n"); if (!checkTypes(context, arg, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_B)) {return;} call Buffer.get(context, arg2->buffer.var, arg->value.var, &element); call Stacks.pushOperand(context, arg); call Stacks.pushOperand(context, &element); break; } case OPbyank: { BombillaStackVariable* arg2 = call Stacks.popOperand(context); BombillaStackVariable element; dbg(DBG_USR1, "Yanking element from buffer\n"); if (!checkTypes(context, arg, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_B)) {return;} call Buffer.yank(context, arg2->buffer.var, arg->value.var, &element); call Stacks.pushOperand(context, arg); call Stacks.pushOperand(context, &element); break; } case OPmotectl: dbg(DBG_ERROR, "VM (%i): Unimplemented class 2 instruction: 0x%hhx.\n", (int)context->which, instr); default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_ERROR, "VM (%i): Unrecognized class 2 instruction: 0x%hhx.\n", (int)context->which, instr); } } void execute3ClassInstruction(BombillaContext* context, uint8_t instr) { BombillaStackVariable* arg1 = call Stacks.popOperand(context); BombillaStackVariable* arg2 = call Stacks.popOperand(context); BombillaStackVariable temp; switch(instr) { case OPswap: dbg(DBG_USR1, "VM (%i): Executing swap.\n", (int)context->which); temp = *arg2; call Stacks.pushOperand(context, arg1); call Stacks.pushOperand(context, &temp); break; case OPland: dbg(DBG_USR1, "VM (%i): Executing land.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg1->value.var & arg2->value.var); break; case OPlor: dbg(DBG_USR1, "VM (%i): Executing lor.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg1->value.var | arg2->value.var); break; case OPand: dbg(DBG_USR1, "VM (%i): Executing add.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg1->value.var && arg2->value.var); break; case OPor: dbg(DBG_USR1, "VM (%i): Executing or.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg1->value.var || arg2->value.var); break; case OPshiftr: dbg(DBG_USR1, "VM (%i): Executing shiftr.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg2->value.var >> arg1->value.var); break; case OPshiftl: dbg(DBG_USR1, "VM (%i): Executing shiftl.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg2->value.var << arg1->value.var); break; case OPadd: dbg(DBG_USR1, "VM (%i): Executing add.\n", (int)context->which); executeAdd(context, arg1, arg2); break; case OPmod: dbg(DBG_USR1, "VM (%i): Executing add.\n", (int)context->which); if (!checkTypes(context, arg1, BOMB_VAR_V) || !checkTypes(context, arg2, BOMB_VAR_V)) {return;} call Stacks.pushValue(context, arg2->value.var % arg1->value.var); break; case OPeq: dbg(DBG_USR1, "VM (%i): Executing eq.\n", (int)context->which); call Stacks.pushValue(context, areEqual(arg1, arg2)); break; case OPneq: dbg(DBG_USR1, "VM (%i): Executing neq.\n", (int)context->which); call Stacks.pushValue(context, !areEqual(arg1, arg2)); break; case OPlt: if ((arg1->type == BOMB_VAR_V) && (arg2->type == BOMB_VAR_V)) { call Stacks.pushValue(context, arg2->value.var < arg1->value.var); } else if ((arg1->type == BOMB_VAR_S) && (arg2->type == BOMB_VAR_S) && (arg1->sense.type == arg2->sense.type)) { call Stacks.pushValue(context, arg2->sense.var < arg1->sense.var); } else { call BombillaError.error(context, BOMB_ERROR_INVALID_TYPE); } break; case OPgt: if ((arg1->type == BOMB_VAR_V) && (arg2->type == BOMB_VAR_V)) { call Stacks.pushValue(context, arg2->value.var > arg1->value.var); } else if ((arg1->type == BOMB_VAR_S) && (arg2->type == BOMB_VAR_S) && (arg1->sense.type == arg2->sense.type)) { call Stacks.pushValue(context, arg2->sense.var > arg1->sense.var); } else { call BombillaError.error(context, BOMB_ERROR_INVALID_TYPE); } break; case OPlte: if ((arg1->type == BOMB_VAR_V) && (arg2->type == BOMB_VAR_V)) { call Stacks.pushValue(context, arg2->value.var <= arg1->value.var); } else if ((arg1->type == BOMB_VAR_S) && (arg2->type == BOMB_VAR_S) && (arg1->sense.type == arg2->sense.type)) { call Stacks.pushValue(context, arg2->sense.var <= arg1->sense.var); } else { call BombillaError.error(context, BOMB_ERROR_INVALID_TYPE); } break; case OPgte: if ((arg1->type == BOMB_VAR_V) && (arg2->type == BOMB_VAR_V)) { call Stacks.pushValue(context, arg2->value.var > arg1->value.var); } else if ((arg1->type == BOMB_VAR_S) && (arg2->type == BOMB_VAR_S) && (arg1->sense.type == arg2->sense.type)) { call Stacks.pushValue(context, arg2->sense.var > arg1->sense.var); } else { call BombillaError.error(context, BOMB_ERROR_INVALID_TYPE); } break; case OPeqtype: call Stacks.pushValue(context, typeEqual(arg1, arg2)); break; default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_ERROR, "VM (%i): Unrecognized class 3 instruction: 0x%hhx.\n", (int)context->which, instr); } } void executeMClassInstruction(BombillaContext* context, uint8_t instr) { uint8_t arg = instr & MARG_MASK; uint8_t* ptr = (uint8_t*)context->header; switch(instr & MINSTR_MASK) { case OPgetms: dbg(DBG_USR1, "VM (%i): Pushing message header short %i onto operand stack.\n", (int)context->which, (int)arg); if (arg >= BOMB_HEADERSIZES) { dbg(DBG_USR1|DBG_ERROR, "VM (%i): getms: index %i out of range .\n", (int)context->which, (int)arg); call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); return; } call Stacks.pushValue(context, context->header[(int)arg]); break; case OPgetmb: dbg(DBG_USR1, "VM (%i): Pushing message header byte %i onto operand stack.\n", (int)context->which, (int)arg); if (arg >= BOMB_HEADERSIZE) { dbg(DBG_USR1|DBG_ERROR, "VM (%i): getmb: index %i out of range .\n", (int)context->which, (int)arg); call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); return; } call Stacks.pushValue(context, (int16_t)ptr[(int)arg]); break; case OPsetms: { BombillaStackVariable* val = call Stacks.popOperand(context); dbg(DBG_USR1, "VM (%i): Setting message header short %i.\n", (int)context->which, (int)arg); if (!checkTypes(context, val, BOMB_VAR_V)) {return;} if (arg >= BOMB_HEADERSIZES) { dbg(DBG_USR1|DBG_ERROR, "VM (%i): setms: index %i out of range .\n", (int)context->which, (int)arg); call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); return; } context->header[arg] = val->value.var; break; } case OPsetmb: { BombillaStackVariable* val = call Stacks.popOperand(context); dbg(DBG_USR1, "VM (%i): Setting message header byte %i.\n", (int)context->which, (int)arg); if (!checkTypes(context, val, BOMB_VAR_V)) {return;} if (arg >= BOMB_HEADERSIZE) { dbg(DBG_USR1|DBG_ERROR, "VM (%i): setmb: index %i out of range .\n", (int)context->which, (int)arg); call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); return; } ptr[arg] = (uint8_t)(val->value.var & 0xff); break; } default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); } } void executeJClassInstruction(BombillaContext* context, uint8_t instr) { uint8_t arg = instr & JARG_MASK; switch(instr & JINSTR_MASK) { case OPjumpc: if (context->condition > 0) { dbg(DBG_USR1, "VM (%i): Condition true, jump to %i.\n", (int)context->which, (int)arg); context->condition--; if (arg < BOMB_PGMSIZE) { context->pc = arg; } else { call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); } } else { dbg(DBG_USR1, "VM (%i): Condition false, do not jump.\n", (int)context->which, (int)arg); } break; case OPjumps: { BombillaStackVariable* cond = call Stacks.popOperand(context); if (!checkTypes(context, cond, BOMB_VAR_V)) {return;} if (cond->value.var > 0) { dbg(DBG_USR1, "VM (%i): Stack variable (%i) true, jump to %i.\n", (int)context->which, (int)cond->value.var, (int)arg); if (arg < BOMB_PGMSIZE) { context->pc = arg; } else { call BombillaError.error(context, BOMB_ERROR_INDEX_OUT_OF_BOUNDS); } } else { dbg(DBG_USR1, "VM (%i): Stack variable false, do not jump.\n", (int)context->which, (int)arg); } break; } default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); } } void executeVClassInstruction(BombillaContext* context, uint8_t instr) { uint8_t arg = instr & VARG_MASK; // Check we have access to the variable if ((context->heldSet & (1 << arg)) == 0) { dbg(DBG_USR1|DBG_ERROR, "VM (%i): Invalid variable access: %i\n", (int)context->which, (int)arg); call BombillaError.error(context, BOMB_ERROR_INVALID_ACCESS); return; } // Access it switch (instr & VINSTR_MASK) { case OPgetvar: dbg(DBG_USR1, "VM (%i): Getting variable %i\n", (int)context->which, (int)arg); call Stacks.pushOperand(context, &(state.heap[arg])); break; case OPsetvar: { BombillaStackVariable* var = call Stacks.popOperand(context); if (!checkTypes(context, var, (BOMB_VAR_V | BOMB_VAR_S))) {break;} dbg(DBG_USR1, "VM (%i): Setting variable %i\n", (int)context->which, (int)arg); state.heap[arg] = *var; break; } default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_ERROR, "VM (%i): Unrecognized v-class instruction: %hhx\n", (int)context->which, instr); } return; } void executeXClassInstruction(BombillaContext* context, uint8_t instr) { int16_t arg = (int16_t)(instr & XARG_MASK); dbg(DBG_USR1, "VM (%i): Executing pushc :%i\n", (int)context->which, (int)arg); call Stacks.pushValue(context, arg); return; } command result_t computeInstruction(BombillaContext* context) { uint8_t instr = context->capsule->capsule.code[(int)context->pc]; // dbg(DBG_USR1, "VM (%hhi): Issuing instruction 0x%hhx.\n", context->which, instr); if (context->state != BOMB_STATE_RUN) { dbg(DBG_ERROR, "VM: (%hhi) Tried to execute instruction in non-run state: %hhi\n", context->which, context->state); return FAIL; } context->pc++; if (call Instruction.isMClass(instr)) { executeMClassInstruction(context, instr); } else if (call Instruction.isVClass(instr)) { executeVClassInstruction(context, instr); } else if (call Instruction.isJClass(instr)) { executeJClassInstruction(context, instr); } else if (call Instruction.isXClass(instr)) { executeXClassInstruction(context, instr); } else { // Basic class uint8_t instrSet = instr >> 4; switch(instrSet) { case 0: execute0ClassInstruction(context, instr); break; case 1: execute1ClassInstruction(context, instr); break; case 2: execute2ClassInstruction(context, instr); break; case 3: execute3ClassInstruction(context, instr); break; default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_ERROR, "VM: Unidentified instruction class. Instruction: %hhx\n", instr); } } return SUCCESS; } event result_t Virus.capsuleInstalled(BombillaCapsule* capsule) { capsuleAnalysis(capsule->type & BOMB_OPTION_MASK); return SUCCESS; } event result_t Virus.enableExecution() { return SUCCESS; } event result_t Virus.disableExecution() { return SUCCESS; } event result_t Virus.capsuleHeard(uint8_t type) { return SUCCESS; } event void Virus.capsuleForce(uint8_t type) { return; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -