Java实现hack汇编器

Hack汇编语言是一种特定于计算机体系结构的汇编语言,使用Hack架构的机器码指令来编写程序。Hack是一种基于Von Neumann结构的计算机体系结构,由Harvard大学的Nand to Tetris项目开发出来,用于实现计算机硬件和软件。

Hack汇编语言主要用于在Nand to Tetris项目中编写计算机硬件和软件。该项目旨在教授计算机系统的基本原理和构造,从最基本的逻辑门开始,一步步地构建出完整的计算机系统,包括CPU、内存、输入/输出、操作系统和编程语言等方面。通过设计和构造这些部分,参与者可以对计算机系统的工作原理有更深入的了解,同时也可以提高程序设计和算法分析能力。

HackAssemblerNoSymbol

按照要求先写一个没有符号的,再写一个有符号的

首先读取文本文件,去掉空白行,然后去掉单独的注释行,除了单独的注释行还有与代码在同一行的尾随代码的注释也要去掉。

然后开始准备翻译hack汇编语言,即翻译A指令和C指令。

对于A指令,如图所示,它的格式是"@"加上一个十进制数字或者一个符号(标签),由于此处我们编写的是无符号的汇编器,所以我们暂时忽略符号的翻译,因此@后面只可能出现数字,所以我们直接将数字变成二进制并进行补0就行。

对于C指令,如图所示,它的格式由三个部分组成:目标位dest、计算位comp和跳转位jmp。因此我们为了方便可以直接建立起dest、comp和jmp三个表方便查询与替换。

然后开始翻译C指令,C指令中的dest和jmp可以为空,因此先根据指令中是否包含=和;分情况提取dest、jmp和comp,再从之前建立的三个表中寻找相应的字符串进行替换。

其中的comp表,分成a=0和a=1两种情况,但是不需要建立两个表,直接在对应的字符串前插入字符0或者1即可

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
import java.util.Scanner;
import java.util.Vector;public class hackAssemblerNoSymbol {public static void main(String[] args) throws IOException {HashMap<String, String> Dest = new HashMap<>(); //目标位替换表Dest.put("null", "000");Dest.put("M", "001");Dest.put("D", "010");Dest.put("MD", "011");Dest.put("A", "100");Dest.put("AM", "101");Dest.put("AD", "110");Dest.put("AMD", "111");HashMap<String, String> Jmp = new HashMap<>(); //跳转位替换表Jmp.put("null", "000");Jmp.put("JGT", "001");Jmp.put("JEQ", "010");Jmp.put("JGE", "011");Jmp.put("JLT", "100");Jmp.put("JNE", "101");Jmp.put("JLE", "110");Jmp.put("JMP", "111");HashMap<String, String>Comp = new HashMap<>(); //计算位替换表// values in comp a=0Comp.put("0", "0101010");Comp.put("1", "0111111");Comp.put("-1", "0111010");Comp.put("D", "0001100");Comp.put("A", "0110000");Comp.put("!D", "0001111");Comp.put("!A", "0110001");Comp.put("-D", "0001111");Comp.put("D+1", "0011111");Comp.put("A+1", "0110111");Comp.put("D-1", "0001110");Comp.put("A-1", "0110010");Comp.put("D+A", "0000010");Comp.put("D-A", "0010011");Comp.put("A-D", "0000111");Comp.put("D&A", "0000000");Comp.put("D|A", "0010101");// values in comp a=1Comp.put("M", "1110000");Comp.put("!M", "1110001");Comp.put("-M", "1110011");Comp.put("M+1", "1110111");Comp.put("M-1", "1110010");Comp.put("D+M", "1000010");Comp.put("D-M", "1010011");Comp.put("M-D", "1000111");Comp.put("D&M", "1000000");Comp.put("D|M", "1010101");Scanner asm = new Scanner(new File("C:\\Users\\Yezi\\Desktop\\Java程序设计\\HW2\\nand2tetris\\projects\\06\\max\\MaxL.asm"));Vector<String>code=new Vector<>();while (asm.hasNextLine()) {String line = asm.nextLine();if (!Objects.equals(line, "") && line.charAt(0) != '/') { //去掉空白行和注释行String[] pure = line.split("/"); //去掉尾随代码的注释pure[0]=pure[0].replaceAll("\\s",""); //去掉空格code.add(pure[0]);}}asm.close();FileWriter binary=new FileWriter(new File("C:\\Users\\Yezi\\Desktop\\Java程序设计\\HW2\\HackAssembler\\MaxL.hack"));for(String line:code){if(line.charAt(0)=='@'){ //A指令String address=line.substring(1); //取@后面的内容int number=Integer.parseInt(address); //取数字String numberBinary=Integer.toBinaryString(number); //数字转二进制String zeros="0".repeat(16-numberBinary.length()); //补0齐16位binary.write(zeros+numberBinary+'\n');}else{ //C指令String dest="null";String jmp="null";String comp;String[] destCompJmp=line.split(";");if(destCompJmp[0].contains("=")){ // 有destString[] destComp=destCompJmp[0].split("=");dest=destComp[0];comp=destComp[1];}else{ //没有destcomp=destCompJmp[0];}if(destCompJmp.length>1){ //有jmpjmp=destCompJmp[1];}binary.write("111"+Comp.get(comp)+Dest.get(dest)+Jmp.get(jmp)+'\n');}}binary.close();}
}

HackAssembler

这个是有符号的

基本与无符号的解决思路相同,所需要特别处理的就是hack汇编语言中的符号。

首先建立起一个符号表,如图所示,将一些系统预定义的符号如R系列寄存器等装入其中。

对于标签符号的处理,需要对代码进行一次扫描,如图所示,确定标签符号的地址,将其加入符号表中。

然后就是处理变量符号了,如图所示,对于变量符号,会将它们放在从地址16开始的空间,因此对于首次出现的变量符号给予它们从16开始的值,再次出现的变量符号就取他们先前赋予的值。

由于只有A指令中涉及到符号,所以我们只需要改变对A指令的翻译即可,在先前的无符号汇编器的编写中我们A指令中@后面只会出现数字,在增加了符号后,@后面可以出现变量、标签和预定义的符号,所以我们需要增加判断条件,先在符号表中寻找相应的匹配符号,如果找到了,直接替换成相应的数值,如果没有找到,再判断是否是数字,如果不是数字,则是首次输出的变量符号,那么将其添加到符号表中即可。

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
import java.util.Scanner;
import java.util.Vector;public class hackAssembler {public static void main(String[] args) throws IOException {HashMap<String,Integer> Symbol=new HashMap<>(); //符号表Symbol.put("SP", 0);Symbol.put("LCL", 1);Symbol.put("ARG", 2);Symbol.put("THIS", 3);Symbol.put("THAT", 4);Symbol.put("SCREEN", 16384);Symbol.put("KBD", 24567);Symbol.put("R0", 0);Symbol.put("R1", 1);Symbol.put("R2", 2);Symbol.put("R3", 3);Symbol.put("R4", 4);Symbol.put("R5", 5);Symbol.put("R6", 6);Symbol.put("R7", 7);Symbol.put("R8", 8);Symbol.put("R9", 9);Symbol.put("R10", 10);Symbol.put("R11", 11);Symbol.put("R12", 12);Symbol.put("R13", 13);Symbol.put("R14", 14);Symbol.put("R15", 15);HashMap<String, String> Dest = new HashMap<>(); //目标位替换表Dest.put("null", "000");Dest.put("M", "001");Dest.put("D", "010");Dest.put("MD", "011");Dest.put("A", "100");Dest.put("AM", "101");Dest.put("AD", "110");Dest.put("AMD", "111");HashMap<String, String> Jmp = new HashMap<>(); //跳转位替换表Jmp.put("null", "000");Jmp.put("JGT", "001");Jmp.put("JEQ", "010");Jmp.put("JGE", "011");Jmp.put("JLT", "100");Jmp.put("JNE", "101");Jmp.put("JLE", "110");Jmp.put("JMP", "111");HashMap<String, String>Comp = new HashMap<>(); //计算位替换表// values in comp a=0Comp.put("0", "0101010");Comp.put("1", "0111111");Comp.put("-1", "0111010");Comp.put("D", "0001100");Comp.put("A", "0110000");Comp.put("!D", "0001111");Comp.put("!A", "0110001");Comp.put("-D", "0001111");Comp.put("D+1", "0011111");Comp.put("A+1", "0110111");Comp.put("D-1", "0001110");Comp.put("A-1", "0110010");Comp.put("D+A", "0000010");Comp.put("D-A", "0010011");Comp.put("A-D", "0000111");Comp.put("D&A", "0000000");Comp.put("D|A", "0010101");// values in comp a=1Comp.put("M", "1110000");Comp.put("!M", "1110001");Comp.put("-M", "1110011");Comp.put("M+1", "1110111");Comp.put("M-1", "1110010");Comp.put("D+M", "1000010");Comp.put("D-M", "1010011");Comp.put("M-D", "1000111");Comp.put("D&M", "1000000");Comp.put("D|M", "1010101");Scanner asm = new Scanner(new File("C:\\Users\\Yezi\\Desktop\\Java程序设计\\HW2\\nand2tetris\\projects\\06\\rect\\Rect.asm"));Vector<String>code=new Vector<>();while (asm.hasNextLine()) {String line = asm.nextLine();if (!Objects.equals(line, "") && line.charAt(0) != '/') { //去掉空白行和注释行String[] pure = line.split("/"); //去掉尾随代码的注释pure[0]=pure[0].replaceAll("\\s",""); //去掉空格if(pure[0].charAt(0)=='('){ //如果是标签符号,将之添加到符号表中String label=pure[0].substring(1,pure[0].length()-1);Symbol.put(label,code.size());}else{code.add(pure[0]); //不是标签是代码}}}asm.close();FileWriter binary=new FileWriter(new File("C:\\Users\\Yezi\\Desktop\\Java程序设计\\HW2\\HackAssembler\\Rect.hack"));int start=16;for(String line:code){if(line.charAt(0)=='@'){ //A指令String address=line.substring(1); //取@后面的内容int number;if(Symbol.containsKey(address)){ // 出现过的符号,预定义符号、变量和标签number=Symbol.get(address);}else if(address.matches("\\d+")){ //数字number=Integer.parseInt(address); //取数字}else{ //首次出现的变量符号number=start++;Symbol.put(address,number);}String numberBinary=Integer.toBinaryString(number); //数字转二进制String zeros="0".repeat(16-numberBinary.length()); //补0齐16位binary.write(zeros+numberBinary+'\n');}else{ //C指令String dest="null";String jmp="null";String comp;String[] destCompJmp=line.split(";");if(destCompJmp[0].contains("=")){ // 有destString[] destComp=destCompJmp[0].split("=");dest=destComp[0];comp=destComp[1];}else{ //没有destcomp=destCompJmp[0];}if(destCompJmp.length>1){ //有jmpjmp=destCompJmp[1];}binary.write("111"+Comp.get(comp)+Dest.get(dest)+Jmp.get(jmp)+'\n');}}binary.close();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/106576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 内核中的pid和前缀树

前言&#xff1a; 写这个文章的初衷是因为今天手写了一个字典树&#xff0c;然后写字典树以后忽然想到了之前看的技术文章&#xff0c;linux kernel 之前的pid 申请方式已经从 bitmap 变成了 基数树&#xff0c;所以打算写文章再回顾一下这种数据结构算法 一、内核中pid的申请…

【学习笔记】minIO分布式文件服务系统

MinIO 一、概述 1.1 minIO是什么&#xff1f; MinIO是专门为海量数据存储、人工智能、大数据分析而设计的对象存储系统。&#xff08;早前流行的还有FastDFS&#xff09; 据官方介绍&#xff0c;单个对象最大可存储5T&#xff0c;非常适合存储海量图片、视频、日志文件、备…

java.sql.SQLFeatureNotSupportedException解决方法

使用MyBatis访问数据库查询数据时报错&#xff1a; Caused by: java.sql.SQLFeatureNotSupportedExceptionat com.alibaba.druid.pool.DruidPooledResultSet.getObject(DruidPooledResultSet.java:1771)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun…

03在命令行环境中创建Maven版的Java工程,了解pom.xml文件的结构,了解Java工程的目录结构并编写代码,执行Maven相关的构建命令

创建Maven版的Java工程 Maven工程的坐标 数学中使用x、y、z三个向量可以在空间中唯一的定位一个点, Maven中也可以使用groupId,artifactId,version三个向量在Maven的仓库中唯一的定位到一个jar包 groupId: 公司或组织域名的倒序, 通常也会加上项目名称代表公司或组织开发的一…

JDBC操作BLOB类型字段

JDBC中Statement接口本身不能直接操作BLOB数据类型 操作BLOB数据类型需要使用PreparedStatement或者CallableStatement(存储过程) 这里演示通过PreparedStatement操作数据库BLOB字段 设置最大传入字节 一般是4M 可以通过以下命令修改 set global max_allowed_packet1024*1…

网页在线打开PDF_网站中在线查看PDF之pdf.js

一、pdf.js简介 PDF.js 是一个使用 HTML5 构建的便携式文档格式查看器。 pdf.js 是社区驱动的&#xff0c;并由 Mozilla 支持。我们的目标是为解析和呈现 PDF 创建一个通用的、基于 Web 标准的平台。 pdf.js 将 PDF 文档转换为 HTML5 Canvas 元素&#xff0c;并使用 JavaScr…

Puppeteer结合测试工具jest使用(四)

Puppeteer结合测试工具jest使用&#xff08;四&#xff09; Puppeteer结合测试工具jest使用&#xff08;四&#xff09;一、简介二、与jest结合使用&#xff0c;集成到常规测试三、支持其他的几种四、总结 一、简介 Puppeteer是一个提供自动化控制Chrome或Chromium浏览器的Node…

MyBatis(中)

目录 1、动态sql&#xff1a; 1、if标签&#xff1a; 2、where标签&#xff1a; 3、 trim标签&#xff1a; 4、set标签&#xff1a; 5、choose when otherwise&#xff1a; 6、模糊查询的写法&#xff1a; 7、foreach标签&#xff1a; &#xff08;1&#xff09;批量删除…

施耐德Unity通过Modbus控制变频器

硬件设备 PLC: Unity Premium (CPU:TSX P57154) 通讯卡: TSX SCP 114 连接电缆: TSX SCP CM 4030 VSD: ATV 58 硬件连接 Unity Premium (CPU: TSX P57154)本身不带Modbus接口&#xff0c;因此&#xff0c;采用TSX SCP 114扩展一个Modbus接口。TSX SCP 114是一个RS-485接…

【已解决】No Python at ‘D:\Python\python.exe‘

起因&#xff0c;我把我的python解释器&#xff0c;重新移了个位置&#xff0c;导致我在Pycharm中的爬虫项目启动&#xff0c;结果出现这个问题。 然后&#xff0c;从网上查到了这篇博客: 【已解决】No Python at ‘D:\Python\python.exe‘-CSDN博客 但是&#xff0c;按照上述…

8.Covector Transformation Rules

上一节已知&#xff0c;任意的协向量都可以写成对偶基向量的线性组合&#xff0c;以及如何通过计算基向量穿过的协向量线来获得协向量分量&#xff0c;且看到 协向量分量 以 与向量分量 相反的方式进行变换。 现要在数学上确认协向量变换规则是什么。 第一件事&#xff1a;…

前端小案例 | 一个带切换的登录注册界面(静态)

文章目录 &#x1f4da;HTML&#x1f4da;CSS&#x1f4da;JS &#x1f4da;HTML <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-sc…

紫光同创FPGA实现UDP协议栈网络视频传输,基于YT8511和RTL8211,提供4套PDS工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的以太网方案紫光同创FPGA精简版UDP方案紫光同创FPGA带ping功能UDP方案 3、设计思路框架OV7725摄像头配置及采集OV5640摄像头配置及采集UDP发送控制视频数据组包数据缓冲FIFOUDP协议栈详解RGMII转GMII动态ARPUDP协议IP地址、端口…

【深度学习 | Transformer】释放注意力的力量:探索深度学习中的 变形金刚,一文带你读通各个模块 —— Positional Encoding(一)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

kettle应用-从数据库抽取数据到excel

本文介绍使用kettle从postgresql数据库中抽取数据到excel中。 首先&#xff0c;启动kettle 如果kettle部署在windows系统&#xff0c;双击运行spoon.bat或者在命令行运行spoon.bat 如果kettle部署在linux系统&#xff0c;需要执行如下命令启动 chmod x spoon.sh nohup ./sp…

视频监控系统/安防视频平台EasyCVR广场视频细节优化

安防视频监控系统/视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防视频汇聚平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;可实现视频监控直播、视频轮播、…

华为9.20笔试 复现

第一题 丢失报文的位置 思路&#xff1a;从数组最小索引开始遍历 #include <iostream> #include <vector> using namespace std; // 求最小索引值 int getMinIdx(vector<int> &arr) {int minidx 0;for (int i 0; i < arr.size(); i){if (arr[i] …

spring boot Rabbit高级教程

消息可靠性 生产者重试机制 首先第一种情况&#xff0c;就是生产者发送消息时&#xff0c;出现了网络故障&#xff0c;导致与MQ的连接中断。 为了解决这个问题&#xff0c;SpringAMQP提供的消息发送时的重试机制。即&#xff1a;当RabbitTemplate与MQ连接超时后&#xff0c;…

【git】500 Whoops, something went wrong on our end.

在访问公的的git 时出现了500错误提示. 500 Whoops, something went wrong on our end. 哎呀&#xff0c;我们这边出了问题。 TMD 出了什么问题了&#xff1f;&#xff1f;&#xff1f;一脸懵逼。 登录git 服务器。 查看git的状态。 命令&#xff1a; gitlab-ctl statu…

互联网Java工程师面试题·Java 总结篇·第一弹

目录 1、面向对象的特征有哪些方面&#xff1f; 2、访问修饰符 public,private,protected,以及不写&#xff08;默认&#xff09;时的区别&#xff1f; 3、String 是最基本的数据类型吗&#xff1f; 4、float f3.4;是否正确&#xff1f; 5、short s1 1; s1 s1 1;有错吗…