Loading... # 引言 前些时候写了一套CrackMe,纯手工古法编程,不用额外插件和第三方库,各种人肉混淆和花指令,结果还是被IDA+MCP秒了,甚是心痛,可是直接上VMP的话,就太不讲武德了,毕竟只是一个玩具,不至于上这种商业化的保护壳。 # 何为虚拟机 这里的虚拟机并非是qemu、virtual box、vmware、hyper-v这样的虚拟机,况且我也做不出来呀,emmm。 这里的虚拟机指的是模拟出来一套CPU,自己写寄存器、缓存、栈、指令集,相当于写了一套中间层,最后还是要宿主机进行计算的。 举个例子: 我要计算1+1,那么CPU内部执行大概是这样的。 ```asm mov eax,1 mov ebx,1 add eax,ebx ``` vm中间层呢 我定义一个CPU结构体 ```cpp struct CPU { int CURR_POS; // 当前选中的寄存器,这是我新引入的一个概念 int STORAGE[BASE_STORAGE_SIZE]; // 寄存器 int DATA_STACK[BASE_STACK_SIZE]; // 栈空间 int DATA_STACK_POS; // 栈指针 } cpu; ``` 然后制定指令集 ```cpp typedef enum { OP_MOV OP_ADD } ``` 定义实现方法 ```cpp 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指令集,混淆指令集,定义多个指令集名称,实现方法不通但是效果相同的等等,提高破解难度。 举个例子: ```cpp 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; ``` 当然这个指令集还是有缺陷的,并且不完整的,写到哪儿就加到哪儿吧。 # 代码怎么写? 这是我比较头痛的事情,因为你制定了指令集,那么你成功的把高级语言转换成了低级语言(仿汇编) 这时候你的代码是这样的 ```cpp 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 ``` © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏