public ExecuteAction Step() { Instruction nextInstruction = NextInstruction; Trace?.TraceInformation("[{0}] {1}", ProgramCounter, nextInstruction); var args = new InstructionEventArgs() { Instruction = nextInstruction }; Executing?.Invoke(this, args); if (args.Action == ExecuteAction.Break) { return(args.Action); } this.Operations[nextInstruction.Opcode](nextInstruction.Operand); Executed?.Invoke(this, args); if (!IsHalted) { if (nextInstruction.Opcode != OpCode.JMP && nextInstruction.Opcode != OpCode.TAC) { ProgramCounter++; } } else { Halted?.Invoke(this, EventArgs.Empty); } return(args.Action); }
public void Run() { BigInteger iptr = 0; while (true) { var opCode = Memory[(int)iptr].ToString("D2"); var parameterModes = opCode.Length > 2 ? opCode.Substring(0, opCode.Length - 2) : ""; if (opCode.EndsWith(OpCodeAdd)) { var modes = ParseParameterModes(parameterModes, 3); var a = GetValueFromMemory(iptr + 1, modes[0]); var b = GetValueFromMemory(iptr + 2, modes[1]); checked { SetValueInMemory(a + b, iptr + 3, modes[2]); } iptr += 4; } else if (opCode.EndsWith(OpCodeMultiply)) { var modes = ParseParameterModes(parameterModes, 3); var a = GetValueFromMemory(iptr + 1, modes[0]); var b = GetValueFromMemory(iptr + 2, modes[1]); checked { SetValueInMemory(a * b, iptr + 3, modes[2]); } iptr += 4; } else if (opCode.EndsWith(OpCodeInput)) { while (StdIn.Count == 0) { Thread.Sleep(1); } StdIn.TryDequeue(out var input); var modes = ParseParameterModes(parameterModes, 1); SetValueInMemory(input, iptr + 1, modes[0]); iptr += 2; } else if (opCode.EndsWith(OpCodeOutput)) { var modes = ParseParameterModes(parameterModes, 1); var output = GetValueFromMemory(iptr + 1, modes[0]); StdOut.Enqueue(output); iptr += 2; } else if (opCode.EndsWith(OpCodeJumpIfNotZero)) { var modes = ParseParameterModes(parameterModes, 2); var value = GetValueFromMemory(iptr + 1, modes[0]); if (value != 0) { var jumpAddress = GetValueFromMemory(iptr + 2, modes[1]); iptr = jumpAddress; } else { iptr += 3; } } else if (opCode.EndsWith(OpCodeJumpIfZero)) { var modes = ParseParameterModes(parameterModes, 2); var value = GetValueFromMemory(iptr + 1, modes[0]); if (value == 0) { var jumpAddress = GetValueFromMemory(iptr + 2, modes[1]); iptr = jumpAddress; } else { iptr += 3; } } else if (opCode.EndsWith(OpCodeLessThan)) { var modes = ParseParameterModes(parameterModes, 3); var a = GetValueFromMemory(iptr + 1, modes[0]); var b = GetValueFromMemory(iptr + 2, modes[1]); if (a < b) { SetValueInMemory(1, iptr + 3, modes[2]); } else { SetValueInMemory(0, iptr + 3, modes[2]); } iptr += 4; } else if (opCode.EndsWith(OpCodeEquals)) { var modes = ParseParameterModes(parameterModes, 3); var a = GetValueFromMemory(iptr + 1, modes[0]); var b = GetValueFromMemory(iptr + 2, modes[1]); if (a == b) { SetValueInMemory(1, iptr + 3, modes[2]); } else { SetValueInMemory(0, iptr + 3, modes[2]); } iptr += 4; } else if (opCode.EndsWith(OpCodeRelativeBaseOffset)) { var modes = ParseParameterModes(parameterModes, 1); var offset = GetValueFromMemory(iptr + 1, modes[0]); RelativeBaseAddress += offset; iptr += 2; } else if (opCode.EndsWith(OpCodeBreak)) { Halted?.Invoke(); break; } else { throw new System.Exception(); } } }