这是我突发奇想的一个项目,用c语言模拟51单片机的运行
整个项目分为三个部分
内存与寄存器模拟器
51汇编编译器
运行器
现在只完成了内存与寄存器部分,而且还只是模拟了部分寄存器,不过我感觉即使只是做成这样工作量也是超级大的。
不知道还会不会更新这个项目了,毕竟这一年时间很关健也很忙,不应该把时间浪费在没有意义的事情上。
也许等以后有空了会填上这个坑吧,也许永远也不会继续去写这个项目了。
下面上代码吧。
mm.h
//存储管理器的头文件
/*
tiny51模拟的存储器 (内存的大小空间都是我们假设的,实际上要比这个从小得多)
16KB的ROM
16KB的RAM
16KB的外接RAM
目前打算模拟的寄存器有
模拟的寄存器有
ACC 累加器
PSW 程序状态字
DPH 数据地址指针高8位
DPL 数据地址指针低8位
SP 堆栈指针
PC 程序计数器
*/
//最后修改时间 2019-4-7 12:15
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//定义一些数据结构//
#define bool int
#define SIZE_OF_ROM 16384 //ROM的内存的大小
#define SIZE_OF_RAM 16384 //RAM的内存大小
#define SIZE_OF_XRAM 16384 //外部RAM的内存大小
enum typeOfMemory{ //内存中数据类型的枚举,后期还会再添加
NONE, //表示空内存
CODE, //代码
DATA //数据
};
/*
ROM是代码存放的地址,也就是C:0x xxxxh 可以索引到的地址
因为PC是16位的,所有ROM最大就是64KB
当取常量表中数据的时候也可以DPTR作为指针,DPTR也是16位的
16 * 1024 = 16384 //开16384个结构体数组模拟64KB的ROM
*/
struct ROM{
enum typeOfMemory type; //记录数据的类型
int8_t opCode; //当前内存存放的操作码
int8_t length; //数据的长度
int16_t index; //当前内存的地址索引,也就是数组索引
}; //可以索引的地址为0-65535
/*
RAM是代码可以操作的存储空间,也就是d:0x xxxxh 可以索引到的地址
也就是用用MOV指令,当第一个操作数是指针或者直接地址的时候索引到的内存
寄存器是8位的,所以可以索引的内存为128B
假设直接地址可以索引16KB内存
RAM区不需要长度,因为就是一个字节一个字节存的
*/
struct RAM{
enum typeOfMemory type; //这里只能是空或者数据
char data; //数据
int16_t index; //地址索引,虚拟机启动的时候要初始化
};
/*
XRAM和RAM没有本质区别,用x:0x xxxxh 可以索引到地址
*/
struct XRAM{
enum typeOfMemory type;
char data;
int16_t index;
};
/*
寄存器还没写呢
*/
//程序状态字
struct PSW{
bool CY; //cy位,用于表示进位,借位
bool AC; //辅助进位标志位,当acc低4位发生进位时置该标志位
bool F0; //通用标志位,用户来定义
bool RS1, RS0; //用于指示使用哪一组工作寄存器
bool OV; //溢出标志位
bool none; //没有用的一位
bool P; //奇偶校验标志位
};
struct commonRegister{
int8_t R[8];
};
struct SRF{ //特殊功能寄存器
int8_t ACC; //8位的累加器
int8_t DPH; //数据指针高8位
int8_t DPL; //数据指针低8位
int8_t SP; //堆栈指针
int16_t PC; //程序计数器,指向下一条将要执行的指令
};
/*
这是内存管理器,实现对上述数据结构的管理
所有的内存数据结构都放在这里
*/
struct memoryManager{ //这里面的内容都要初始化
//内存模块
struct ROM CodeMemory[SIZE_OF_ROM];
struct RAM DataMemory[SIZE_OF_RAM];
struct XRAM XDataMemory[SIZE_OF_XRAM];
//特殊