不等了。关于CPU模拟的解决方案发布 及 散分!
本来是clcqifeng问T、P版的问题。不过P版好像不在,T版一如既往的不知所云。之后Z版的参与激发了我的兴趣。在上学时考过高级程序员。其中要考一个叫CASL的汇编语言,是用在一台叫COMET的抽象计算机上的。
当时这个东西让我觉得很扯,抽象计算机,只是个概念。学着学着就动了个念头,为什么不实现一个虚拟的COMET来实际运行一下?
于是我写了一个COMET虚拟机,以及CASL编译器。用来编译执行用CASL写的汇编代码。
呵呵,昨天我试着找了找看能不能找到我的COMET,可惜没找到,我电脑都换了三台了。
本来一直在等Z版的方案。不过看起来Z版要打长久战了。呵呵,恕我直言,我觉得Z版的解决方案有点复杂了,别介意我这么说,请按照你的思路完成下去。
我的思路很简单,建立这个CPU的硬件执行环境的模型,用软件模拟硬件的工作过程。所以我的代码是建立一个虚拟机。
指令集也是开放式的,可以随意定义和修改。
由于只测试了原楼主的两个示例,不排除里面存在缺陷。
欢迎各位下载源代码编译测试。有什么问题或意见欢迎跟贴讨论。
程序代码:
/*************************************************************** r1 r2 r3 0001 复制操作 00010011 复制r3到r2 00010101 复制r3到r1 00010110 复制r2到r1 00011011 复制r2到r3 00011101 复制r1到r3 00011110 复制r1到r2 0010 加法 00100011 将r2与r3相加,结果存放在r2 00100101 将r1与r3相加,结果存放在r1 00100110 将r1与r2相加,结果存放在r1 00101011 将r3与r2相加,结果存放在r3 00101101 将r3与r1相加,结果存放在r3 00101110 将r2与r1相加,结果存放在r2 0011 减法 00110011 用r2减去r3,结果存放在r2 00110101 用r1减去r3,结果存放在r1 00110110 用r1减去r2,结果存放在r1 00111011 用r3减去r2,结果存放在r3 00111101 用r3减去r1,结果存放在r3 00111110 用r2减去r1,结果存放在r2 0100 移动到register 01000011 将r3中存放的地址的数据放到r2中 01000101 将r3中存放的地址的数据放到r1中 01000110 将r2中存放的地址的数据放到r1中 01001011 将r2中存放的地址的数据放到r3中 01001101 将r1中存放的地址的数据放到r3中 01001110 将r1中存放的地址的数据放到r2中 01000100 xxxxxxxx 数字X放到r1中 01000010 xxxxxxxx 数字X放到r2中 01000001 xxxxxxxx 数字X放到r3中 0101 移动到memory 01010011 将r2中存放的数据放到r3所指的内存地址中去 01010101 将r1中存放的数据放到r3所指的内存地址中去 01010110 将r1中存放的数据放到r2所指的内存地址中去 01011011 将r3中存放的数据放到r2所指的内存地址中去 01011101 将r3中存放的数据放到r1所指的内存地址中去 01011110 将r2中存放的数据放到r1所指的内存地址中去 0110 为零跳转 01100011 如果r2的值为零,则跳转到r3所指的代码处 01100101 如果r1的值为零,则跳转到r3所指的代码处 01100110 如果r1的值为零,则跳转到r2所指的代码处 01101011 如果r3的值为零,则跳转到r2所指的代码处 01101101 如果r3的值为零,则跳转到r1所指的代码处 01101110 如果r2的值为零,则跳转到r1所指的代码处 0111 不为零跳转 01110011 如果r2的值不为零,则跳转到r3所指的代码处 01110101 如果r1的值不为零,则跳转到r3所指的代码处 01110110 如果r1的值不为零,则跳转到r2所指的代码处 01111011 如果r3的值不为零,则跳转到r2所指的代码处 01111101 如果r3的值不为零,则跳转到r1所指的代码处 01111110 如果r2的值不为零,则跳转到r1所指的代码处 1000 打印 10000100 打印r1所指向的内存地址的数字 10000010 打印r2所指向的内存地址的数字 10000001 打印r3所指向的内存地址的数字 10001100 打印r1所指向的内存地址的字符串,字符串以0结尾 10001010 打印r2所指向的内存地址的字符串,字符串以0结尾 10001001 打印r3所指向的内存地址的字符串,字符串以0结尾 11110000 程序结束 ***************************************************************/ #include<stdio.h> #include<string.h> #define VM_MEMORY_SIZE 0xFF #define VM_END 0 #define VM_RUN 1 #define VM_ERR 2 typedef struct { unsigned char pc; unsigned char r1; unsigned char r2; unsigned char r3; unsigned char code[VM_MEMORY_SIZE]; unsigned char data[VM_MEMORY_SIZE]; }VM; void vm_initialize(VM * virtual_machine); int vm_single_step(VM * virtual_machine); int vm_run(VM * virtual_machine, char * code, int code_length); int str_to_code(char * str, char * code); int main() { VM vm; char str[2048]; char code[256]; int len, ret; for(;;) { printf("VM > "); fgets(str, 2048, stdin); len = str_to_code(str, code); if(len == 0) break; ret = vm_run(&vm, code, len); switch(ret) { case VM_END: printf("\nOVER\n"); break; case VM_ERR: printf("\nERROR\n"); break; } } return 0; } void vm_initialize(VM *vm) { int i; vm->pc = 0; vm->r1 = 0; vm->r2 = 0; vm->r3 = 0; for(i = 0; i < VM_MEMORY_SIZE; i++) { vm->code[i] = 0; vm->data[i] = 0; } } int vm_single_step(VM *vm) { int code; code = vm->code[vm->pc++]; switch(code) { case 0x13: vm->r2 = vm->r3; break; case 0x15: vm->r1 = vm->r3; break; case 0x16: vm->r1 = vm->r2; break; case 0x1B: vm->r3 = vm->r2; break; case 0x1D: vm->r3 = vm->r1; break; case 0x1E: vm->r2 = vm->r1; break; case 0x23: vm->r2 += vm->r3; break; case 0x25: vm->r1 += vm->r3; break; case 0x26: vm->r1 += vm->r2; break; case 0x2B: vm->r3 += vm->r2; break; case 0x2D: vm->r3 += vm->r1; break; case 0x2E: vm->r2 += vm->r1; break; case 0x33: vm->r2 -= vm->r3; break; case 0x35: vm->r1 -= vm->r3; break; case 0x36: vm->r1 -= vm->r2; break; case 0x3B: vm->r3 -= vm->r2; break; case 0x3D: vm->r3 -= vm->r1; break; case 0x3E: vm->r2 -= vm->r1; break; case 0x41: vm->r3 = vm->code[vm->pc++]; break; case 0x42: vm->r2 = vm->code[vm->pc++]; break; case 0x43: vm->r2 = vm->data[vm->r3]; break; case 0x44: vm->r1 = vm->code[vm->pc++]; break; case 0x45: vm->r1 = vm->data[vm->r3]; break; case 0x46: vm->r1 = vm->data[vm->r2]; break; case 0x4B: vm->r3 = vm->data[vm->r2]; break; case 0x4D: vm->r3 = vm->data[vm->r1]; break; case 0x4E: vm->r2 = vm->data[vm->r1]; break; case 0x53: vm->data[vm->r3] = vm->r2; break; case 0x55: vm->data[vm->r3] = vm->r1; break; case 0x56: vm->data[vm->r2] = vm->r1; break; case 0x5B: vm->data[vm->r2] = vm->r3; break; case 0x5D: vm->data[vm->r1] = vm->r3; break; case 0x5E: vm->data[vm->r1] = vm->r2; break; case 0x63: if(vm->r2 == 0) vm->pc = vm->r3; break; case 0x65: if(vm->r1 == 0) vm->pc = vm->r3; break; case 0x66: if(vm->r1 == 0) vm->pc = vm->r2; break; case 0x6B: if(vm->r3 == 0) vm->pc = vm->r2; break; case 0x6D: if(vm->r3 == 0) vm->pc = vm->r1; break; case 0x6E: if(vm->r2 == 0) vm->pc = vm->r1; break; case 0x73: if(vm->r2 != 0) vm->pc = vm->r3; break; case 0x75: if(vm->r1 != 0) vm->pc = vm->r3; break; case 0x76: if(vm->r1 != 0) vm->pc = vm->r2; break; case 0x7B: if(vm->r3 != 0) vm->pc = vm->r2; break; case 0x7D: if(vm->r3 != 0) vm->pc = vm->r1; break; case 0x7E: if(vm->r2 != 0) vm->pc = vm->r1; break; case 0x81: printf("%d", (char)vm->data[vm->r3]); break; case 0x82: printf("%d", (char)vm->data[vm->r2]); break; case 0x84: printf("%d", (char)vm->data[vm->r1]); break; case 0x89: printf("%s", vm->data + vm->r3); break; case 0x8A: printf("%s", vm->data + vm->r2); break; case 0x8C: printf("%s", vm->data + vm->r1); break; case 0xF0: vm->pc--; return VM_END; default: vm->pc--; return VM_ERR; } return VM_RUN; } int vm_run(VM *vm, char *code, int len) { int i, j; vm_initialize(vm); for(i = 0; i < len && code[i] != (char)0xF0; i++) vm->code[i] = code[i]; if(i < len && code[i] == (char)0xF0) vm->code[i] = 0xF0; for(i++, j = 0; i < len; i++, j++) vm->data[j] = code[i]; while((i = vm_single_step(vm)) == VM_RUN); return i; } int str_to_code(char * str, char * code) { char delimiters[] = " \r\n"; char * token; int i, len = 0; for(token = strtok(str, delimiters); token != NULL; token = strtok(NULL, delimiters)) { for(i = 0; *token == '0' || *token == '1'; token++) i = (i << 1) + *token - '0'; code[len++] = i; } return len; }