| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2161 人关注过本帖, 1 人收藏
标题:不等了。关于CPU模拟的解决方案发布 及 散分!
只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
结帖率:100%
收藏(1)
已结贴  问题点数:100 回复次数:34 
不等了。关于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;
}
收到的鲜花
  • pangding2012-03-12 23:14 送鲜花  10朵   附言:你要乐意可以给自己加个精,方便后人发现这 ...
搜索更多相关主题的帖子: 高级程序员 计算机 虚拟机 编译器 三台 
2012-03-10 23:10
于祥
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:5
帖 子:1047
专家分:4132
注 册:2011-4-24
收藏
得分:6 
占座

最基础的往往是你最容易忽略的!
2012-03-10 23:14
smallmoon521
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:517
专家分:1373
注 册:2008-4-21
收藏
得分:6 
我是膜拜来的

为游戏狂~~!!    大家努力编哈!
2012-03-10 23:34
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:6 
// 能具体说下这个函数吗?
int vm_run(VM *vm, char *code, int len)

我就是真命天子,顺我者生,逆我者死!
2012-03-11 00:11
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
vm->data 是做什么用的?
图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册

C:\Documents and Settings\Administrator\Local Settings\Application Data\TheWorld\Chrome\Application\4.0.4.314\plugins

[ 本帖最后由 BlueGuy 于 2012-3-11 18:51 编辑 ]

我就是真命天子,顺我者生,逆我者死!
2012-03-11 00:35
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 BlueGuy

void vm_initialize(VM * virtual_machine);
int vm_single_step(VM * virtual_machine);
int vm_run(VM * virtual_machine, char * code, int code_length);
以及VM结构,共同构成了虚拟机的整体

data code模拟两段内存,一段存数据,一段存代码。至于为什么这么做请参见原贴示例。
合并在一起也不是不可以。方法有增加段基址寄存器、扩大指令计数器范围等等。总之就是区分开数据段与代码段。

不好意思,需要出去办点事,晚上回来再聊

重剑无锋,大巧不工
2012-03-11 08:10
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:6 
膜拜大牛

技术问题,请不要以短消息方式提问
2012-03-11 12:43
你们都要疼我哦
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:火星
等 级:贵宾
威 望:49
帖 子:1296
专家分:2746
注 册:2008-7-13
收藏
得分:6 
指令不分离出来,不对二进制opcode进行解析。。。这样的实现,似乎有点取巧,
谈不上“模拟”cpu。
至于说虚拟机。。。 虚拟的太上层了

小妹,哥哥看你骨骼清奇,绝非凡人,将来必成大业,不如这样,你先把裤裤脱了,待哥哥为你开启灵窍,然后我们一起努力钻研如何
2012-03-11 13:03
fanliguang
Rank: 2
等 级:论坛游民
帖 子:31
专家分:52
注 册:2012-2-26
收藏
得分:6 
佩服,看不懂的
2012-03-11 13:26
hf201089
Rank: 2
等 级:论坛游民
帖 子:48
专家分:25
注 册:2012-3-4
收藏
得分:6 
看不懂
2012-03-11 15:16
快速回复:不等了。关于CPU模拟的解决方案发布 及 散分!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020409 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved