纯C打造轻量级brainfuck脚本语言解释器

来源:互联网 发布:js获取月为两位数 编辑:程序博客网 时间:2024/05/20 06:56

本人大一,最近在搞CTF的时候偶然发现一种很好玩的脚本语言(应该算是吧吐舌头)brainfuck,顾名思义这种语言很变态(强奸你的脑子偷笑


brainfuck是图灵完全的,也就是说,你用C写的所有程序、算法都可以用brainfuck实现。它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF偷笑就象它的名字所暗示的,brainfuck程序很难读懂。尽管如此,brainfuck图灵机一样可以完成任何计算任务。虽然brainfuck的计算方式如此与众不同,但它确实能够正确运行。这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。






因为CTF那道提通关必须要去翻译出一长串恶心的指令敲打,像我这么懒的人怎么可能会去老老实实想呢,虽然网上有现成的解释器可以用,但最近因为刚刚大一,想锻炼自己编程能力,决定自己写一个解释器,好在它的指令并不多大笑,可能是我编程水平太烂了吧,经过n个小时冥(hu)思(luan)苦(xia)想(gao),终于有了下面的代码

#include <stdio.h>

#include <string.h>

#include <windows.h>#define max 30000char code[max]={0};int sourc[max]={0};char data[8]={'+','-','>','<',',','.','[',']'};//指令表int ptr=0;//数据指针int eip;//指令指针int ret[max]={0};//循环返回地址int loop=0;//跟踪返回指针BOOL check(int length){    int i,k;    for(i=0;i<length;i++)//编程时要注意边界检查    {        for(k=0;k<8;k++)        {            if(code[i]==data[k])            {                break;            }        }        if(k==8)        {            printf("代码第%d含有非法命令:%c",i,code[i]);            return FALSE;        }    }    return TRUE;}int format(int length)//扫描并保存代码中的“[”和“]”一个表中{    int i,j;    for(i=0,j=0;i<length;i++)    {        if((code[i]=='[')||(code[i]==']'))        {            ret[j++]=i;        }    }    return j;}void addnum()//+操作{    sourc[ptr]++;    eip++;    return;}void subnum()//-操作{    sourc[ptr]--;    eip++;    return;}void addptr()//指针右移操作>{    ptr++;    eip++;    return;}void subptr()//指针左移操作<{    ptr--;    eip++;    return;}void print()//打印操作{    printf("%c",sourc[ptr]);    eip++;    return;}void get()//读取操作{    scanf("%d",sourc+ptr);    eip++;    return;}void leftloop(int len)//当执行到[,表示循环开始,就像C语言的while(...){,{    sourc[ptr]<=0?eip=ret[loop=(len-1-loop)]+1:eip++;//sourc数组中保存整个程序需要的数据,初始全部为0,可以用他们来控制循环    return;//len-1-loop这样理解,有[  [  ]  ],在数组中的位置用下标loop跟踪,0,1,2,3,len是长度,就是C语言中循环嵌套循环体的意思}void rightloop(int len){    eip=ret[loop=(len-1-loop)];//作用类似C语言的  }    return;}int main(){    char name[200];    int len,p=0;    scanf("%s",name);    FILE *fp;    if(!(fp=fopen(name,"r")))    {        printf("错误文件!\n");        system("pause");        return;    }    while((code[p++]=fgetc(fp))!=EOF);//读取脚本文件    len=strlen(code)-1;//因为fgetc会多读入一个文件末尾标志数据,所以长度要减一    if(!check(len))    {        system("pause");        return;    }    int length=format(len);    for(eip=0;eip<len;)    {        switch(code[eip])        {            case '+':addnum();break;            case '-':subnum();break;            case '>':addptr();break;            case '<':subptr();break;            case '.':print();break;            case ',':get();break;            case '[':leftloop(length);loop++;break;            case ']':rightloop(length);break;        }    }    fclose(fp);    system("pause");    return;}

唉,我表达的不好,代码也写的很糟糕,可能不好理解,委屈,也去网上看过那些大牛写的brainfuck解释器,他们比我写的好多了,思路也和我完全不一样难过,我太菜了,因为以前学过汇编语言,所以我的本意就是用C语言模拟近似cpu的操作,eip,ret........之类的,写的不好,请各位嘴下留情微笑

0 0
原创粉丝点击