c语言手搓一套cpu虚拟机

引言

前些时候写了一套CrackMe,纯手工古法编程,不用额外插件和第三方库,各种人肉混淆和花指令,结果还是被IDA+MCP秒了,甚是心痛,可是直接上VMP的话,就太不讲武德了,毕竟只是一个玩具,不至于上这种商业化的保护壳。

何为虚拟机

这里的虚拟机并非是qemu、virtual box、vmware、hyper-v这样的虚拟机,况且我也做不出来呀,emmm。
这里的虚拟机指的是模拟出来一套CPU,自己写寄存器、缓存、栈、指令集,相当于写了一套中间层,最后还是要宿主机进行计算的。

举个例子:
我要计算1+1,那么CPU内部执行大概是这样的。

mov eax,1
mov ebx,1
add eax,ebx

vm中间层呢
我定义一个CPU结构体

struct CPU
{
    int CURR_POS; // 当前选中的寄存器,这是我新引入的一个概念
    int STORAGE[BASE_STORAGE_SIZE]; // 寄存器
    int DATA_STACK[BASE_STACK_SIZE]; // 栈空间
    int DATA_STACK_POS; // 栈指针
} cpu;

然后制定指令集

typedef enum
{
    OP_MOV
    OP_ADD
}

定义实现方法

void op_mov(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = arg;
}

void op_add(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] += arg;
}

这时候,我执行op_mov,op_add即可实现加法计算。

指令集的定义

这里需要大概了解一下CPU的实际指令集是什么,然后模拟出来一套自己的指令集,也可以自己diy指令集,混淆指令集,定义多个指令集名称,实现方法不通但是效果相同的等等,提高破解难度。

举个例子:

typedef enum
{
    OP_INIT,         // 初始化寄存器, 从num开始往后赋值0
    OP_SEL,          // 选择当前指向寄存器
    OP_MOV,          // 把值赋给选中的寄存器
    OP_ADD,          // 选中的寄存器值+给的值
    OP_SUB,          // 选中的寄存器值-给的值
    OP_IMUL,         // 选中的寄存器值乘以给的值
    OP_MOV_REG,      // 给定寄存器的值赋值给选中的寄存器
    OP_ADD_REG,      // 选中的寄存器加上给定寄存器的值
    OP_SUB_REG,      // 选中的寄存器减去给定寄存器的值
    OP_MUL_REG,      // 选中的寄存器乘以给定寄存器的值
    OP_BIT_MOV,      // 选中的寄存器位移给定的值
    OP_JMP,          // 跳转到指定行
    OP_JZ,           // 如果选中的寄存器是0,那么跳转到指定地址
    OP_JNZ,          // 如果选中的寄存器不是0,那么跳转到指定地址
    OP_INC,          // 选中的寄存器自增
    OP_DEC,          // 选中的寄存器自减
    OP_AND,          // 选中的寄存器与运算
    OP_XOR,          // 选中的寄存器异或运算
    OP_OR,           // 选中的寄存器或运算
    OP_PUSH,         // 给定的寄存器序列推入栈
    OP_POP,          // 推出栈中最后一个元素到给定的寄存器序列
    OP_NOP,          // 啥也不做
    OP_NOP_N,        // 作废后面N个指令
    OP_END,          // 处理器结束标识
    DBG_CPU,         // 输出寄存器和栈空间
    OP_PRINT,        // 输出指定寄存器的值
    OP_STORE_CACHE,  // 存储缓存
    OP_DEC_CACHE,    // 解密缓存
    OP_CACHE_LEN,    // 获取缓存有多少个,并且把结果写道当前选中的寄存器中
    OP_CACHE_LEN_ID, // 获取指定ID的缓存有多长,并且放到当前选中的寄存器中
    OP_CACHE_START,  // 获取缓存的开始索引,并且放到当前选中的寄存器中
    OP_CACHE_GET,    // 获取缓存中当前寄存器中的索引,到指定寄存器中
    OP_JMP_P,        // 跳转到当前PC+参数行
    OP_JZ_P,         // 如果当前选中的寄存器是0,跳转到当前PC+参数行
    OP_JNZ_P,        // 如果当前选中的寄存器不是0,跳转到当前PC+参数行
    OP_JE_P,         // 如果当前选中的寄存器等于指定的寄存器,跳转到当前PC+参数行
    OP_INT3,         // 调试断点
} COMMAND;

当然这个指令集还是有缺陷的,并且不完整的,写到哪儿就加到哪儿吧。

代码怎么写?

这是我比较头痛的事情,因为你制定了指令集,那么你成功的把高级语言转换成了低级语言(仿汇编)
这时候你的代码是这样的

code[CMD_MAX_SIZE] = {
        OP_INIT, 0,
        OP_SEL, 0,
        OP_ADD, 5,
        OP_IMUL, 20,
        OP_SUB, 13,
        OP_ADD_REG, 1,
        OP_SEL, 0x01,
        OP_ADD, 14,

维护成本极高,逻辑跳转非常复杂

完整代码

指令集的实现没有经过完全确认和测试!

#include <stdio.h>
#include "hardware.h"
#include <stdlib.h>


void vm_run(int* code, const size_t len)
{
    int pc = 0;
    while (pc >= 0 && pc < len)
    {
        const int op = code[pc++] ^ ((VM_KEY2 ^ VM_KEY) + 2 * (VM_KEY2 & VM_KEY) - (VM_KEY2 + VM_KEY));
        const int arg = code[pc++];
        printf("[%d] %s %d\n", pc - 2, command_name[op], arg);
        handlers[op](arg, &pc, code);
    }
}

int main()
{
    int magic = 114514;
    int magic2 = 1919810;

    int code[CMD_MAX_SIZE] = {
        OP_INIT, 0,
        OP_SEL, 0,
        OP_ADD, 5,
        OP_NOP_N, 3, 123, 456, 789, //
        OP_IMUL, 20,
        OP_SUB, 13,
        OP_ADD_REG, 1,
        OP_SEL, 0x01,
        OP_ADD, 14,
        OP_IMUL, 52,
        OP_BIT_MOV, -2,
        OP_SEL, 0,
        OP_MUL_REG, 1,
        OP_BIT_MOV, 2,
        OP_IMUL, 2,
        OP_JZ, 2,
        OP_NOP, 0xFF12B8,
        OP_NOP_N, 3, 2, 1, 0,
        OP_STORE_CACHE, 26, 'A' ^ VM_KEY, 'B' ^ VM_KEY, 'C' ^ VM_KEY, 'D' ^ VM_KEY, 'E' ^ VM_KEY, 'F' ^ VM_KEY,
        'G' ^ VM_KEY, 'H' ^ VM_KEY, 'I' ^ VM_KEY, 'J' ^ VM_KEY, 'K' ^ VM_KEY, 'L' ^ VM_KEY, 'M' ^ VM_KEY, 'N' ^ VM_KEY,
        'O' ^ VM_KEY, 'P' ^ VM_KEY, 'Q' ^ VM_KEY, 'R' ^ VM_KEY, 'S' ^ VM_KEY, 'T' ^ VM_KEY, 'U' ^ VM_KEY, 'V' ^ VM_KEY,
        'W' ^ VM_KEY, 'X' ^ VM_KEY, 'Y' ^ VM_KEY, 'Z' ^ VM_KEY, //
        OP_STORE_CACHE, 26, 'a' ^ VM_KEY, 'b' ^ VM_KEY, 'c' ^ VM_KEY, 'd' ^ VM_KEY, 'e' ^ VM_KEY, 'f' ^ VM_KEY,
        'g' ^ VM_KEY, 'h' ^ VM_KEY, 'i' ^ VM_KEY, 'j' ^ VM_KEY, 'k' ^ VM_KEY, 'l' ^ VM_KEY, 'm' ^ VM_KEY, 'n' ^ VM_KEY,
        'o' ^ VM_KEY, 'p' ^ VM_KEY, 'q' ^ VM_KEY, 'r' ^ VM_KEY, 's' ^ VM_KEY, 't' ^ VM_KEY, 'u' ^ VM_KEY, 'v' ^ VM_KEY,
        'w' ^ VM_KEY, 'x' ^ VM_KEY, 'y' ^ VM_KEY, 'z' ^ VM_KEY,
        OP_NOP,0X1000400,
        OP_SUB, 0x2F00,
        OP_SEL, 1,
        OP_ADD_REG, 0,
        OP_IMUL, 0x1BF,
        OP_BIT_MOV, 0x5,
        OP_SEL, 2,
        OP_ADD_REG, 0,
        OP_ADD, 0xFB1,
        OP_XOR, 0x520,
        OP_IMUL, 0xF,
        OP_ADD_REG, 0,
        OP_ADD, 0x43C0,
        OP_SEL, 1,
        OP_BIT_MOV, 6,
        OP_ADD, 0x40A,
        OP_ADD_REG, 2,
        OP_SEL, 2,
        OP_SEL, 0,
        OP_ADD, -0x7E,
        OP_SEL, 3,
        OP_MOV, 0,
        OP_CACHE_LEN_ID, 1, // R3 存储的是mem长度
        OP_SEL, 4,
        OP_CACHE_START, 1, // R4 存储的是mem的开始位置
        OP_SEL, 5,
        OP_ADD_REG, 3,
        OP_ADD_REG, 4, // R5 存储的是结束位
        OP_SEL, 4,
        OP_INT3,0,
        OP_CACHE_GET, 6,
        OP_PRINT, 6,
        OP_INC, 0,
        OP_JE_P, 5, 2, // 往下不算本身,往上算本身,指的是跳转参数开始计数
        OP_JMP_P, -11, // 同上
        OP_MOV, '\n',
        OP_PRINT,-1,
        DBG_CPU, 1,
        OP_END, 0,
    };


    vm_run(code, CMD_MAX_SIZE);
    // int cur_pos = 0; // 已知的初始化位置
    // char name[16];
    // scanf("%s", name);
    // for (int i = 0; i < name[i] != '\0'; i++)
    // {
    //     code[cur_pos++] = OP_ADD;
    //     code[cur_pos++] = name[i];
    //     code[cur_pos++] = OP_SEL;
    //     code[cur_pos++] = (i + 1) % BASE_STORAGE_SIZE;
    // }
    // code[cur_pos++] = DBG_CPU; // 调试输出cpu
    // code[cur_pos++] = 0;
    // code[cur_pos++] = OP_END; // 结束虚拟机
    // code[cur_pos++] = 0;
    // vm_run(code, CMD_MAX_SIZE);
    return 0;
}
//
// Created by 36083 on 2026/4/22.
//
#pragma once

#define BASE_STORAGE_SIZE 16
#define BASE_STACK_SIZE 64
#define BASE_MEM_SIZE 65536
#define CMD_MAX_SIZE 10240
typedef void (*op_handler)(int arg, int *pc, int code[]);

#define TEA_MAGIC 0x9E3779B9
#define MAGIC_SBOX(x) ((x ^ 0x6a09e667) + 0xbb67ae85)

int VM_KEY = 0xF3;
int VM_KEY2 = 0x1911F;


struct CPU
{
    int CURR_POS;
    int STORAGE[BASE_STORAGE_SIZE];
    int DATA_STACK[BASE_STACK_SIZE];
    int DATA_STACK_POS;
} cpu;

struct CACHE
{
    int cache[BASE_MEM_SIZE];
    int cache_size;                        // 已经占用的空间
    int cache_pos;                         // 当前缓存的索引,也就是接下来要写入时数据的位置
    int cache_start[BASE_MEM_SIZE - 1];    // 开始索引
    int cache_data_len[BASE_MEM_SIZE - 1]; // 数据长度长度
    int cache_len;                         // 有多少个数据
} cache;

typedef enum
{
    OUT_OF_STORAGE_INDEX,
    OUT_OF_STACK_INDEX,
    PC_NUM_EXCEPT,
    OUT_OF_CACHE_INDEX,
    OUT_OF_CACHE_SIZE,
} EXCEPTION;

char command_name[1000][1000] = {
    "OP_INIT",
    "OP_SEL",
    "OP_MOV",
    "OP_ADD",
    "OP_SUB",
    "OP_IMUL",
    "OP_MOV_REG",
    "OP_ADD_REG",
    "OP_SUB_REG",
    "OP_MUL_REG",
    "OP_BIT_MOV",
    "OP_JMP",
    "OP_JZ",
    "OP_JNZ",
    "OP_INC",
    "OP_DEC",
    "OP_AND",
    "OP_XOR",
    "OP_OR",
    "OP_PUSH",
    "OP_POP",
    "OP_NOP",
    "OP_NOP_N",
    "OP_END",
    "DBG_CPU",
    "OP_PRINT",
    "OP_STORE_CACHE",
    "OP_DEC_CACHE",
    "OP_CACHE_LEN",
    "OP_CACHE_LEN_ID",
    "OP_CACHE_START",
    "OP_CACHE_GET",
    "OP_JMP_P",
    "OP_JZ_P",
    "OP_JNZ_P",
    "OP_JE_P",
    "OP_INT3"};

typedef enum
{
    OP_INIT,         // 初始化寄存器, 从num开始往后赋值0
    OP_SEL,          // 选择当前指向寄存器
    OP_MOV,          // 把值赋给选中的寄存器
    OP_ADD,          // 选中的寄存器值+给的值
    OP_SUB,          // 选中的寄存器值-给的值
    OP_IMUL,         // 选中的寄存器值乘以给的值
    OP_MOV_REG,      // 给定寄存器的值赋值给选中的寄存器
    OP_ADD_REG,      // 选中的寄存器加上给定寄存器的值
    OP_SUB_REG,      // 选中的寄存器减去给定寄存器的值
    OP_MUL_REG,      // 选中的寄存器乘以给定寄存器的值
    OP_BIT_MOV,      // 选中的寄存器位移给定的值
    OP_JMP,          // 跳转到指定行
    OP_JZ,           // 如果选中的寄存器是0,那么跳转到指定地址
    OP_JNZ,          // 如果选中的寄存器不是0,那么跳转到指定地址
    OP_INC,          // 选中的寄存器自增
    OP_DEC,          // 选中的寄存器自减
    OP_AND,          // 选中的寄存器与运算
    OP_XOR,          // 选中的寄存器异或运算
    OP_OR,           // 选中的寄存器或运算
    OP_PUSH,         // 给定的寄存器序列推入栈
    OP_POP,          // 推出栈中最后一个元素到给定的寄存器序列
    OP_NOP,          // 啥也不做
    OP_NOP_N,        // 作废后面N个指令
    OP_END,          // 处理器结束标识
    DBG_CPU,         // 输出寄存器和栈空间
    OP_PRINT,        // 输出指定寄存器的值
    OP_STORE_CACHE,  // 存储缓存
    OP_DEC_CACHE,    // 解密缓存
    OP_CACHE_LEN,    // 获取缓存有多少个,并且把结果写道当前选中的寄存器中
    OP_CACHE_LEN_ID, // 获取指定ID的缓存有多长,并且放到当前选中的寄存器中
    OP_CACHE_START,  // 获取缓存的开始索引,并且放到当前选中的寄存器中
    OP_CACHE_GET,    // 获取缓存中当前寄存器中的索引,到指定寄存器中
    OP_JMP_P,        // 跳转到当前PC+参数行
    OP_JZ_P,         // 如果当前选中的寄存器是0,跳转到当前PC+参数行
    OP_JNZ_P,        // 如果当前选中的寄存器不是0,跳转到当前PC+参数行
    OP_JE_P,         // 如果当前选中的寄存器等于指定的寄存器,跳转到当前PC+参数行
    OP_INT3,         // 调试断点
} COMMAND;

void op_init(int arg, int *pc, int code[]);
void op_sel(int arg, int *pc, int code[]);
void op_mov(int arg, int *pc, int code[]);
void op_add(int arg, int *pc, int code[]);
void op_sub(int arg, int *pc, int code[]);
void op_imul(int arg, int *pc, int code[]);
void op_mov_reg(int arg, int *pc, int code[]);
void op_add_reg(int arg, int *pc, int code[]);
void op_sub_reg(int arg, int *pc, int code[]);
void op_mul_reg(int arg, int *pc, int code[]);
void op_bit_mov(int arg, int *pc, int code[]);
void op_jmp(int arg, int *pc, int code[]);
void op_jz(int arg, int *pc, int code[]);
void op_jnz(int arg, int *pc, int code[]);
void op_inc(int arg, int *pc, int code[]);
void op_dec(int arg, int *pc, int code[]);
void op_and(int arg, int *pc, int code[]);
void op_xor(int arg, int *pc, int code[]);
void op_or(int arg, int *pc, int code[]);
void op_push(int arg, int *pc, int code[]);
void op_pop(int arg, int *pc, int code[]);
void op_nop(int arg, int *pc, int code[]);
void op_nop_n(int arg, int *pc, int code[]);
void op_end(int arg, int *pc, int code[]);
void dbg_cpu(int arg, int *pc, int code[]);
void op_print(int arg, int *pc, int code[]);
void op_store_cache(int arg, int *pc, int code[]);
void op_dec_cache(int arg, int *pc, int code[]);
void op_cache_len(int arg, int *pc, int code[]);
void op_cache_len_id(int arg, int *pc, int code[]);
void op_cache_start(int arg, int *pc, int code[]);
void op_cache_get(int arg, int *pc, int code[]);
void op_jmp_p(int arg, int *pc, int code[]);
void op_jz_p(int arg, int *pc, int code[]);
void op_jnz_p(int arg, int *pc, int code[]);
void op_je_p(int arg, int *pc, int code[]);
void op_int3(int arg, int *pc, int code[]);

void HALT(EXCEPTION expect, int *pc);

op_handler handlers[] = {
    op_init,
    op_sel,
    op_mov,
    op_add,
    op_sub,
    op_imul,
    op_mov_reg,
    op_add_reg,
    op_sub_reg,
    op_mul_reg,
    op_bit_mov,
    op_jmp,
    op_jz,
    op_jnz,
    op_inc,
    op_dec,
    op_and,
    op_xor,
    op_or,
    op_push,
    op_pop,
    op_nop,
    op_nop_n,
    op_end,
    dbg_cpu,
    op_print,
    op_store_cache,
    op_dec_cache,
    op_cache_len,
    op_cache_len_id,
    op_cache_start,
    op_cache_get,
    op_jmp_p,
    op_jz_p,
    op_jnz_p,
    op_je_p,
    op_int3,
};

void op_init(int arg, int *pc, int code[])
{
    cpu.DATA_STACK_POS = 0;
    cache.cache_size = 0;
    cache.cache_pos = 0;
    cache.cache_len = 0;
    for (int i = arg; i < BASE_STORAGE_SIZE; i++)
    {
        op_sel(i, pc, code);
        op_mov(0, pc, code);
    }
}

void op_sel(int arg, int *pc, int code[])
{
    if (arg < BASE_STORAGE_SIZE && arg >= 0)
        cpu.CURR_POS = arg;
    else
        HALT(OUT_OF_STORAGE_INDEX, pc);
}

void op_mov(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = arg;
}

void op_add(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] += arg;
}

void op_sub(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] -= arg;
}

void op_imul(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] *= arg;
}

void op_mov_reg(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = cpu.STORAGE[arg];
}

void op_add_reg(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] += cpu.STORAGE[arg];
}

void op_sub_reg(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] -= cpu.STORAGE[arg];
}

void op_mul_reg(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] *= cpu.STORAGE[arg];
}

void op_bit_mov(int arg, int *pc, int code[])
{
    if (arg > 0)
        cpu.STORAGE[cpu.CURR_POS] >>= arg;
    else
        cpu.STORAGE[cpu.CURR_POS] <<= -arg;
}

void op_jmp(int arg, int *pc, int code[])
{
    *pc = arg;
}

void op_jz(int arg, int *pc, int code[])
{
    if (!cpu.STORAGE[cpu.CURR_POS])
        *pc = arg;
}

void op_jnz(int arg, int *pc, int code[])
{
    if (cpu.STORAGE[cpu.CURR_POS])
        *pc = arg;
}

void op_inc(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS]++;
}

void op_dec(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS]--;
}

void op_and(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = cpu.STORAGE[cpu.CURR_POS] & arg;
}

void op_xor(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = cpu.STORAGE[cpu.CURR_POS] ^ arg;
}

void op_or(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = cpu.STORAGE[cpu.CURR_POS] | arg;
}

void op_push(int arg, int *pc, int code[])
{
    if (cpu.DATA_STACK_POS < 0 || cpu.DATA_STACK_POS >= BASE_STACK_SIZE)
        HALT(OUT_OF_STACK_INDEX, pc);
    if (arg >= BASE_STORAGE_SIZE || arg < -1)
        HALT(OUT_OF_STORAGE_INDEX, pc);
    cpu.DATA_STACK[cpu.DATA_STACK_POS++] = cpu.STORAGE[arg == -1 ? cpu.CURR_POS : arg];
}

void op_pop(int arg, int *pc, int code[])
{
    if (cpu.DATA_STACK_POS <= 0 || cpu.DATA_STACK_POS >= BASE_STACK_SIZE)
        HALT(OUT_OF_STACK_INDEX, pc);
    if (arg >= BASE_STORAGE_SIZE || arg < -1)
        HALT(OUT_OF_STORAGE_INDEX, pc);
    cpu.STORAGE[arg == -1 ? cpu.CURR_POS : arg] = cpu.DATA_STACK[--cpu.DATA_STACK_POS];
}

void op_nop(int arg, int *pc, int code[])
{
    *pc ^= VM_KEY;
    *pc ^= VM_KEY;
}

void op_nop_n(int arg, int *pc, int code[])
{
    arg = arg > 0 ? arg : -arg;
    op_nop(arg, pc, code);
    *pc += arg;
}

void op_end(int arg, int *pc, int code[])
{
    *pc = 0xFFFFFF;
}

void dbg_cpu(int arg, int *pc, int code[])
{
    printf("==================================STORAGE================================\n");
    for (int i = 0; i < BASE_STORAGE_SIZE; i++)
    {
        printf("=R=%2d : %d\t", i, cpu.STORAGE[i]);
        if (i % 6 == 0 && i != 0)
            printf("\n");
    }
    printf("\n==================================STACK==================================\n");
    for (int i = 0; i < BASE_STORAGE_SIZE; i++)
    {
        printf("=S=%2d : %d\t", i, cpu.DATA_STACK[i]);
        if (i % 6 == 0 && i != 0)
            printf("\n");
    }
    printf("\n=========================================================================\n");
}

void HALT(EXCEPTION expect, int *pc)
{
    switch (expect)
    {
    case OUT_OF_STACK_INDEX:
        printf("Out of stack index\n");
        break;
    case OUT_OF_STORAGE_INDEX:
        printf("Out of storage index\n");
        break;
    case PC_NUM_EXCEPT:
        printf("PC num except\n");
        break;
    case OUT_OF_CACHE_SIZE:
        printf("Out of cache size\n");
        break;
    case OUT_OF_CACHE_INDEX:
        printf("Out of cache index\n");
        break;
    }
    *pc = -1;
    printf("====================EXCEPT====================\n");
    printf("=PC= : %d\n", *pc);
    printf("=CPOS= : %d\n", cpu.CURR_POS);
    printf("=SPOS= : %d\n", cpu.DATA_STACK_POS);
    printf("==============================================\n");
}

void op_print(int arg, int *pc, int code[])
{
    if (arg < -1 || arg >= BASE_STORAGE_SIZE)
        HALT(OUT_OF_STORAGE_INDEX, pc);
    putchar(cpu.STORAGE[arg == -1 ? cpu.CURR_POS : arg]);
}

void op_store_cache(int arg, int *pc, int code[])
{
    if (cache.cache_size + arg > BASE_MEM_SIZE)
        HALT(OUT_OF_CACHE_SIZE, pc);
    cache.cache_start[cache.cache_len] = cache.cache_pos ^ 0;
    cache.cache_data_len[cache.cache_len] = arg;
    for (int i = 0; i < arg; i++)
    {
        cache.cache_size++;
        cache.cache[cache.cache_pos++] = code[(*pc)++] ^ VM_KEY;
    }
    cache.cache_len++;
}

void op_dec_cache(int arg, int *pc, int code[])
{
    if (arg >= cache.cache_len)
        HALT(OUT_OF_CACHE_INDEX, pc);
    for (int i = cache.cache_start[arg]; i < cache.cache_start[arg] + cache.cache_data_len[arg]; i++)
    {
        cache.cache[i] = cache.cache[i] ^ VM_KEY;
    }
}

void op_cache_len(int arg, int *pc, int code[])
{
    cpu.STORAGE[cpu.CURR_POS] = cache.cache_len;
}

void op_cache_len_id(int arg, int *pc, int code[])
{
    if (arg >= cache.cache_len)
        HALT(OUT_OF_CACHE_INDEX, pc);
    cpu.STORAGE[cpu.CURR_POS] = cache.cache_data_len[arg];
}

void op_cache_start(int arg, int *pc, int code[])
{
    if (arg >= cache.cache_len)
        HALT(OUT_OF_CACHE_INDEX, pc);
    cpu.STORAGE[cpu.CURR_POS] = cache.cache_start[arg];
}

void op_cache_get(int arg, int *pc, int code[])
{
    cpu.STORAGE[arg] = cache.cache[cpu.STORAGE[cpu.CURR_POS]];
}

void op_jmp_p(int arg, int *pc, int code[])
{
    *pc = *pc + arg;
}

void op_jnz_p(int arg, int *pc, int code[])
{
    if (cpu.STORAGE[cpu.CURR_POS])
    {
        *pc = *pc + arg;
    }
}

void op_jz_p(int arg, int *pc, int code[])
{
    if (!cpu.STORAGE[cpu.CURR_POS])
    {
        *pc = *pc + arg;
    }
}

void op_je_p(int arg, int *pc, int code[])
{
    if (cpu.STORAGE[cpu.CURR_POS] == cpu.STORAGE[arg])
    {
        *pc = *pc + code[(*pc)];
    }
    *pc += 1;
}

void op_int3(int arg, int *pc, int code[])
{
    printf("");
}

示例输出:

[0] OP_INIT 0
[2] OP_SEL 0
[4] OP_ADD 5
[6] OP_NOP_N 3
[11] OP_IMUL 20
[13] OP_SUB 13
[15] OP_ADD_REG 1
[17] OP_SEL 1
[19] OP_ADD 14
[21] OP_IMUL 52
[23] OP_BIT_MOV -2
[25] OP_SEL 0
[27] OP_MUL_REG 1
[29] OP_BIT_MOV 2
[31] OP_IMUL 2
[33] OP_JZ 2
[35] OP_NOP 16716472
[37] OP_NOP_N 3
[42] OP_STORE_CACHE 26
[70] OP_STORE_CACHE 26
[98] OP_NOP 16778240
[100] OP_SUB 12032
[102] OP_SEL 1
[104] OP_ADD_REG 0
[106] OP_IMUL 447
[108] OP_BIT_MOV 5
[110] OP_SEL 2
[112] OP_ADD_REG 0
[114] OP_ADD 4017
[116] OP_XOR 1312
[118] OP_IMUL 15
[120] OP_ADD_REG 0
[122] OP_ADD 17344
[124] OP_SEL 1
[126] OP_BIT_MOV 6
[128] OP_ADD 1034
[130] OP_ADD_REG 2
[132] OP_SEL 2
[134] OP_SEL 0
[136] OP_ADD -126
[138] OP_SEL 3
[140] OP_MOV 0
[142] OP_CACHE_LEN_ID 1
[144] OP_SEL 4
[146] OP_CACHE_START 1
[148] OP_SEL 5
[150] OP_ADD_REG 3
[152] OP_ADD_REG 4
[154] OP_SEL 4
[156] OP_INT3 0
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
a[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
b[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
c[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
d[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
e[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
f[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
g[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
h[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
i[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
j[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
k[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
l[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
m[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
n[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
o[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
p[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
q[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
r[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
s[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
t[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
u[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
v[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
w[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
x[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
y[162] OP_INC 0
[164] OP_JE_P 5
[167] OP_JMP_P -11
[158] OP_CACHE_GET 6
[160] OP_PRINT 6
z[162] OP_INC 0
[164] OP_JE_P 5
[169] OP_MOV 10
[171] OP_PRINT -1

[173] DBG_CPU 1
==================================STORAGE================================
=R= 0 : 114514  =R= 1 : 1919810 =R= 2 : 1893119 =R= 3 : 26      =R= 4 : 10      =R= 5 : 52      =R= 6 : 122
=R= 7 : 0       =R= 8 : 0       =R= 9 : 0       =R=10 : 0       =R=11 : 0       =R=12 : 0
=R=13 : 0       =R=14 : 0       =R=15 : 0
==================================STACK==================================
=S= 0 : 0       =S= 1 : 0       =S= 2 : 0       =S= 3 : 0       =S= 4 : 0       =S= 5 : 0       =S= 6 : 0
=S= 7 : 0       =S= 8 : 0       =S= 9 : 0       =S=10 : 0       =S=11 : 0       =S=12 : 0
=S=13 : 0       =S=14 : 0       =S=15 : 0
=========================================================================
[175] OP_END 0

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。