博客
关于我
实践: 《编码:隐匿在计算机软硬件背后的语言》 -- 实现一个简单的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/

你可能感兴趣的文章
Netty 的 Handler 链调用机制
查看>>
Netty 编解码器详解
查看>>
Netty 解决TCP粘包/半包使用
查看>>
Netty 调用,效率这么低还用啥?
查看>>
Netty+Protostuff实现单机压测秒级接收35万个对象实践经验分享
查看>>
Netty+SpringBoot+FastDFS+Html5实现聊天App详解(一)
查看>>
netty--helloword程序
查看>>
Netty5.x 和3.x、4.x的区别及注意事项(官方翻译)
查看>>
netty——bytebuf的创建、内存分配与池化、组成、扩容规则、写入读取、内存回收、零拷贝
查看>>
netty——Channl的常用方法、ChannelFuture、CloseFuture
查看>>
netty——EventLoop概念、处理普通任务定时任务、处理io事件、EventLoopGroup
查看>>
netty——Future和Promise的使用 线程间的通信
查看>>
netty——Handler和pipeline
查看>>
Vue输出HTML
查看>>
netty——黏包半包的解决方案、滑动窗口的概念
查看>>
Netty中Http客户端、服务端的编解码器
查看>>
Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息
查看>>
Netty中实现多客户端连接与通信-以实现聊天室群聊功能为例(附代码下载)
查看>>
Netty中的组件是怎么交互的?
查看>>
Netty中集成Protobuf实现Java对象数据传递
查看>>