博客
关于我
实践: 《编码:隐匿在计算机软硬件背后的语言》 -- 实现一个简单的8位CPU的虚拟机
阅读量:371 次
发布时间:2019-03-04

本文共 2274 字,大约阅读时间需要 7 分钟。

最近在看Charles Petzold的《编码》这本书。书上用生动的例子从导线灯泡继电器开关自己搭建了一个简单的8位计算机。

并且能实现加法,减法,条件判断,调整的基本功能。

这里博主为了巩固对书上知识的理解,用C++模拟书上的方法自己实现了一个8位的CPU虚拟机,并且支持内存的输入输出,和机器码。能自己编码运行程序。

Project Site:

https://github.com/sesiria/CodeMachine

1. 结构设计

采用C++ 来实现这个简单的8位计算机。

首先程序由主菜单(UI)

基本输入(获取各种命令)

执行命令(执行菜单项对应的命令)

整个程序是一个主循环,并且在进入和 退出主循环会进行虚拟机的初始化和反初始化(释放内存)等操作。

当然在执行命令过程中也运行进行中途初始化(Reset命令)

// Main function.int main(int argc, char * argv[], char* env[]) {	char sCommand[BUFSIZ];	initMachine();	printWelcome();	// main loop for standard IO	while (true){		getCommand(sCommand, _countof(sCommand));		if (processCommand(sCommand) == false)			break;	}	uninitMachine();	return 0;}

2. 基本输入输出

基本输入包括输入主菜单的各种命令。

Welcome to the Code Virtual Machine       v0.1 - Author: SesiriaPlease Input command:1. Input instructions(machine code). (I)2. Input assembly code. (A)3. Run code. (S)4. Reset machine. (R)5. Dump memory. (D)6. View Register. (V)7. Help. (H)8. Exit. (E)>
一个获取命令的函数getCommand( 用于获取用户的输入命令)和处理命令的函数processCommand(用于处理用户的选择的命令)。处理命令的过程会忽略无效的用户输入。如果用户选择了退出则直接退出主循环,并指向后续的关闭虚拟机的操作。

以下将说明各菜单项的命令和简单实现:

2.1. 输入代码 

基本输入中最重要的功能就是输入代码(机器指令)以16进制的方式向内测地址输入数据(可以是指令也可以是数据)通过函数

processInputInstruction()来实现。 

该函数判断用户的输入格式,如果是数据则在当前所指向的地址存入用户的输入数据(如果是无效数据会提示无效输入并继续的等待用户输入)并使地址指针指向下一个字节的内存单元(加1)。

用户的输入也可以是[地址]  数据 的方式。 改命令会修改当前指向的内存地址指针,随后输入的数据将以当前内存地址指针为基准,逐步递增。

该函数还对每次地址指针的自增做一个判断若指向内存的最后一个单元则自动指回 0x0000 (第一个单元)。

2.2 输入汇编

由于汇编代码的输入需要设计到字符串处理和宏处理,这里放到后续补完。

2.3 执行代码

将虚拟机指令指针所指向的第一条指令开始逐步执行,直到遇到HLT指令停止。

2.4 复位机器

2.5 显示内存内容

3. 机器内部结构模拟

首先设计一个结构体来存储机的RAM和各种寄存器。

typedef struct _kernalObj{	unsigned char * m_BUF;			// the main memory for the machine	unsigned char  m_A;				// the main register for the machine.	unsigned char  m_CI;			// the 'Carry character' In register for the accumulator.	unsigned char  m_CO;			// the 'Carry character' Out register for the accumulator.	unsigned char  m_ZF;			// the output zero flag for the accumulator.	unsigned char  m_CODE;			// the register for the Instructions	unsigned char  m_CL;			// the low 8bit address register for the Code.	unsigned char  m_CH;			// the high 8bit address register for the Code.	unsigned char  m_IP;			// the Instruction Pointer point to the memory address.}kernalObj;

initMachine()对虚拟机的个成员进行初始化操作,

uninitMachine() 会释放其中的m_BUF成员。

机器支持的指令表

4. 实现代码

转载地址:http://hobg.baihongyu.com/

你可能感兴趣的文章
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
Nhibernate的第一个实例
查看>>
NHibernate示例
查看>>
nid修改oracle11gR2数据库名
查看>>
NIFI1.21.0/NIFI1.22.0/NIFI1.24.0/NIFI1.26.0_2024-06-11最新版本安装_采用HTTP方式_搭建集群_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0_java.net.SocketException:_Too many open files 打开的文件太多_实际操作---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_插入时如果目标表中已存在该数据则自动改为更新数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0058
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0_Postgresql和Mysql同时指定库_指定多表_全量同步到Mysql数据库以及Hbase数据库中---大数据之Nifi工作笔记0060
查看>>
NIFI1.21.0最新版本安装_连接phoenix_单机版_Https登录_什么都没改换了最新版本的NIFI可以连接了_气人_实现插入数据到Hbase_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0最新版本安装_配置使用HTTP登录_默认是用HTTPS登录的_Https登录需要输入用户名密码_HTTP不需要---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增加修改实时同步_使用JsonPath及自定义Python脚本_03---大数据之Nifi工作笔记0055
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_插入修改删除增量数据实时同步_通过分页解决变更记录过大问题_01----大数据之Nifi工作笔记0053
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
查看>>
NIFI1.23.2_最新版_性能优化通用_技巧积累_使用NIFI表达式过滤表_随时更新---大数据之Nifi工作笔记0063
查看>>