Last active
October 13, 2023 07:22
-
-
Save roachsinai/e670d0281ce6973682fa17bd12416ff3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://www.zhihu.com/question/33084689/answer/58994758 | |
#include <stdio.h> | |
#include <string.h> | |
typedef struct inst | |
{ | |
unsigned char code; // 指令 | |
unsigned char cond; // 执行该指令的条件 | |
short p1, p2; // 参数1、2 | |
} inst_t; | |
typedef unsigned short data_t; // 我们操作的就是16位数 | |
typedef struct vm_state | |
{ | |
int ip; // 指令ptr | |
int flag; // 记录最后判断的标志 | |
inst_t *code; // 代码段地址 | |
data_t *data; // 数据段地址 | |
} vm_state_t; | |
#define IADD 1 // 加法 | |
#define ISUB 2 // 减法 | |
#define ICMP 3 // 判断 | |
#define IJMP 4 // 跳转 | |
#define IMOV 5 // 赋值 | |
#define ISTIP 6 // 保存IP | |
#define ILDIP 7 // 设置IP(跳转) | |
#define ILD 8 // 加载一个立即数 | |
#define IOUT 9 // 输出 | |
#define ISTOP 255 // 挂起虚拟机 | |
#define FNA 0 // 任何状态下都执行 | |
#define FEQ 1 // 状态为“相等”时执行 | |
#define FNE 2 // 状态为“不等”时执行 | |
void execute(vm_state_t *state) | |
{ | |
for (;;) // 执行到挂起为止 | |
{ | |
inst_t current = state->code[state->ip]; | |
state->ip++; // 取出指令以后自动ip后移 | |
if (current.cond != FNA && current.cond != state->flag) | |
// 该指令要求的状态不符合当前状态,略过 | |
continue; | |
switch (current.code) | |
{ | |
case IADD: | |
// 将p1指向的数据加上p2指向的数据 | |
state->data[current.p1] += state->data[current.p2]; | |
break; | |
case ISUB: | |
state->data[current.p1] -= state->data[current.p2]; | |
break; | |
case ICMP: | |
// 比较p1指向的数据和p2指向的数据 | |
if (state->data[current.p1] == state->data[current.p2]) | |
state->flag = FEQ; | |
else | |
state->flag = FNE; | |
break; | |
case IJMP: | |
// 跳转,指令根据p1进行偏移 | |
state->ip += current.p1; | |
break; | |
case IMOV: | |
// 将p1指向的数据设置为p2指向的数据 | |
state->data[current.p1] = state->data[current.p2]; | |
break; | |
case ISTIP: | |
// 把IP保存到p1指向的数据 | |
state->data[current.p1] = (data_t) state->ip; | |
break; | |
case ILDIP: | |
// 将IP设置为p1指向的数据,该指令会导致跳转 | |
state->ip = state->data[current.p1]; | |
break; | |
case ILD: | |
// 将立即数p2加载到p1指向的数据 | |
state->data[current.p1] = current.p2; | |
break; | |
case IOUT: | |
// 输出p1指向的数据 | |
printf("%d\n", state->data[current.p1]); | |
break; | |
case ISTOP: | |
return; | |
} | |
} | |
} | |
inst_t sample_code[] = | |
{ | |
{ ILD, FNA, 2, 101 }, | |
{ ILD, FNA, 3, 1 }, | |
{ ILD, FNA, 1, 1 }, | |
{ ILD, FNA, 0, 0 }, | |
{ ICMP, FNA, 1, 2 }, | |
{ IJMP, FEQ, 3, 0 }, | |
{ IADD, FNA, 0, 1 }, | |
{ IADD, FNA, 1, 3 }, | |
{ IJMP, FNA, -5, 0 }, | |
{ IOUT, FNA, 0, 0 }, | |
{ ISTOP, FNA, 0, 0 } | |
}; | |
data_t data_seg[16]; | |
int main(int argn, char *argv[]) | |
{ | |
vm_state_t state; | |
memset(&state, 0, sizeof(state)); | |
state.code = sample_code; | |
state.data = data_seg; | |
execute(&state); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment