#include <stdio.h> typedef enum { A = 0, B, C, D } Registers; typedef enum { FLAG_ZERO = 1, FLAG_NEGATIVE = 1 << 1, } Flags; typedef enum { OP_ADD, OP_ADD_VALUE, OP_HALT, OP_JMP_REL, OP_JMP_REL_NEGATIVE, OP_JMP_REL_NOT_EQUAL, OP_LOAD, OP_MOV, OP_XCHG, OP_NOP, OP_PRINT, OP_TEST, } OpCode; static void set_flags(int value, int *flags_register) { int new_flags = 0; if (value == 0) new_flags |= FLAG_ZERO; if (value < 0) new_flags |= FLAG_NEGATIVE; *flags_register = new_flags; } int main() { int program[] = { OP_LOAD, A, 3, OP_LOAD, B, 5, OP_ADD, B, OP_PRINT, A, OP_LOAD, B, 1, OP_ADD, B, OP_PRINT, A, OP_LOAD, A, 0, OP_LOAD, B, 0, OP_PRINT, A, OP_ADD_VALUE, 3, OP_XCHG, A, B, OP_ADD_VALUE, 1, OP_TEST, 10, OP_XCHG, A, B, OP_JMP_REL_NOT_EQUAL, -16, OP_HALT }; int registers[4] = { 0 }; int flags_register = 0; int *ip = program; while (1) { OpCode op = *ip++; switch (op) { case OP_LOAD: { int idx = *ip++; registers[idx] = *ip++; set_flags(registers[idx], &flags_register); break; } case OP_ADD: { int val = registers[*ip++]; registers[A] += val; set_flags(registers[A], &flags_register); break; } case OP_ADD_VALUE: { int val = *ip++; registers[A] += val; break; } case OP_JMP_REL: { int val = *ip++; ip += val; break; } case OP_NOP: { break; } case OP_TEST: { int val = *ip++; int new_val = val - registers[A]; set_flags(new_val, &flags_register); break; } case OP_JMP_REL_NOT_EQUAL: { int val = *ip++; if (!(flags_register & FLAG_ZERO)) { ip += val; } break; } case OP_JMP_REL_NEGATIVE: { int val = *ip++; if (!(flags_register & FLAG_NEGATIVE)) { ip += val; } break; } case OP_MOV: { int dst = *ip++; int src = *ip++; registers[dst] = registers[src]; break; } case OP_XCHG: { int r1 = *ip++; int r2 = *ip++; int tmp = registers[r1]; registers[r1] = registers[r2]; registers[r2] = tmp; break; } case OP_PRINT: printf("%d\n", registers[*ip++]); break; case OP_HALT: return 0; default: fprintf(stderr, "Unknown instruction %d\n", *ip); return -1; } } return 0; }