Java实现hack汇编器

news2024/11/18 20:15:27

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=0
        Comp.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=1
        Comp.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("=")){ // 有dest
                    String[] destComp=destCompJmp[0].split("=");
                    dest=destComp[0];
                    comp=destComp[1];
                }else{ //没有dest
                    comp=destCompJmp[0];
                }
                if(destCompJmp.length>1){ //有jmp
                    jmp=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=0
        Comp.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=1
        Comp.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("=")){ // 有dest
                    String[] destComp=destCompJmp[0].split("=");
                    dest=destComp[0];
                    comp=destComp[1];
                }else{ //没有dest
                    comp=destCompJmp[0];
                }
                if(destCompJmp.length>1){ //有jmp
                    jmp=destCompJmp[1];
                }
                binary.write("111"+Comp.get(comp)+Dest.get(dest)+Jmp.get(jmp)+'\n');
            }
        }
        binary.close();
    }
}

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

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

相关文章

FPGA面试题(5)

一.FPGA可以综合实现为RAM/ROM/CAM的三种资源及注意事项 三种资源&#xff1a;BLOCK RAM&#xff0c;触发器&#xff08;FF&#xff09;&#xff0c;查找表&#xff08;LUT&#xff09; 注意事项&#xff1a; 1.生成RAM&#xff0c;首选BLOCK RAM。因为BLOCK RAM是已经存在的“…

Jmeter压测http接口和java代码放在Jmeter执行

Jmeter无缝支持java语言&#xff0c;使其在市场上有很高的占有率&#xff0c;一些公司还专门对JMenter进行二次开发&#xff0c;使其成为公司级压测平台。 本次介绍JMenter的一些入门级使用&#xff0c;方便大家继续深入探索。 1、启动Jmeter 2、压测简单http接口 添加线程组…

Ant Design Vue设置表格滚动 宽度自适应 不换行

Ant Design Vue设置表格滚动 宽度自适应 不换行 添加以下属性即可解决这个问题&#xff1a; <a-table :columns"columns" :data-source"list":pagination"false"bordered:scroll"{ x: max-content }" >

Lazysysadmin靶机

信息收集 主机发现 nmap -sn 192.168.88.0/24 //-sn&#xff1a;制作主机发现&#xff0c;不做端口扫描&#xff1b;扫描结果包含本机IP 端口扫描 nmap --min-rate 10000 -p- 192.168.88.136 扫描端口详细信息 端口扫描发现&#xff0c;该主机的22、80、139、445、3306、…

进阶JAVA篇- DateTimeFormatter 类与 Period 类、Duration类的常用API(八)

目录 1.0 DateTimeFormatter 类的说明 1.1 如何创建格式化器的对象呢&#xff1f; 1.2 DateTimeFormatter 类中的 format&#xff08;LocalDateTime ldt&#xff09; 实例方法 2.0 Period 类的说明 2.1 Period 类中的 between(localDate1,localDate2) 静态方法来创建对象。 3.…

vue过渡动画效果

官网:https://cn.vuejs.org/v2/api/#transition 要与v-show,v-if 动态组件结合 给需要过渡的元素外层加<transition> ,并用name命名 , show:true, --------------------- <button click"show!show">button</button> <transition namefade>&…

基本地址变换机构

基本地址变换机构&#xff1a;用于实现逻辑地址到物理地址转换的一组硬件机构。 关于页号页表的定义&#xff0c;放个本人的传送门 1.页表寄存器 基本地址变换机构可以借助进程的页表将逻辑地址转换为物理地址。 1.作用 通常会在系统中设置一个页表寄存器&#xff08;PTR&…

KubeVela交付

有什么用我也不想说了&#xff0c;这个是k8s CI/CD,进阶玩家玩的了&#xff0c;比你们喜欢Arg CD更科学&#xff0c;更现代 在 Kubernetes 中安装 KubeVela helm repo add kubevela https://charts.kubevela.net/core helm repo update helm install --create-namespace -n v…

云耀云服务器L实例部署k8s测评|华为云云耀云服务器L实例评测使用体验

文章目录 云耀云服务器L实例部署k8s测评名词解释云耀云服务器L实例云耀负载均衡k8s及使用场景1.3.1 微服务架构1.3.2 自动化部署1.3.3 弹性伸缩1.3.4 多租户环境1.3.5 持续集成和持续部署 3. 部署华为云云耀服务器L实例3.1 云耀服务器L实例购买3.1.1 云耀服务器L实例初始化配置…

【Golang】grpc环境踩的坑

关于’protoc-gen-go’ 不是内部或外部命令 这个问题的出现是因为没有这个文件导致的 这个文件要通过我们下载的google.golang.org这个文件编译生成的 这里建议下载google提供的grpc包 protobuf的源码&#xff1a; git clone https://github.com/golang/protobuf 下载好之后进…

华为云云耀云服务器L实例评测|企业项目最佳实践之建议与总结(十二)

华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践系列&#xff1a; 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测&#xff5…

RTSP协议

1 前言 RTSP协议作为音视频实时监控一个非常重要的协议&#xff0c;具有非常广泛的应用。RTSP由RFC 2326规范化&#xff0c;它允许客户端通过请求不同的媒体资源来控制流媒体服务器。RTSP是一种应用层协议&#xff0c;通常基于TCP连接&#xff0c;用于建立和控制媒体会话。这使…

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程前言准备工具anaconda/cuda/cudnnanaconda创建环境(选做)安装原…

Jetpack:008-Icon与Image

文章目录 1. 概念介绍2. 使用方法2.1 Icon2.2 Image 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中与Button相关的内容&#xff0c;本章回中主要I con与Image。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我们在本章回中介绍…

graphviz报错

报错如下&#xff1a; graphviz.backend.ExecutableNotFound: failed to execute dot, make sure the Graphviz executables are on your systems PATH 大家习惯pip install graphviz去安装&#xff0c;但是graphviz是个软件&#xff0c;不能单独用Pip安装。 1、下载安装 G…

英语——语法——从句——非谓语动词——笔记

一、1定义 定义&#xff1a; 非谓语动词不是真正意义上的谓语动词&#xff0c;即在句中都不能单独作谓语。 非谓语动词主要有以下三种形式&#xff1a; 技巧&#xff1a;分析句子是先缩短为主谓宾&#xff0c;某人做某事&#xff0c;其他成分都是修饰限定作用。要么修饰明代词…

ECharts的基本使用

目录 一、使用前提 1、安装 2、创建文件 二、LineView.vue文件【相当于一个组件】 1、导入 2、methods方法下写init(){}方法进行选择 3、methods方法下写setOptioin(option) 4、init()函数调用 5、整合完整代码 三、IndexView.vue文件【实现组件引入显示】 1、引入 …

P34~36第八章相量法

8.1复数 复数可表示平面矢量、也可表示正弦量。特别是: 当复数表示正弦量的时候&#xff0c;此时复数称为相量。 8.2复数运算 复数除法也可看做乘法&#xff0c;乘法的几何意义是旋转&#xff08;辐角相加&#xff09;( e^x e^y e^xy)&#xff0c;同时伸缩&#xff08;模变…

计算机操作系统-第七天

1、计算机操作系统的结构&#xff08;续集&#xff09; 分层结构 特性&#xff1a;最底层是硬件&#xff0c;最高层是用户接口&#xff0c;每层只可使用更低的相邻层所提供的功能接口&#xff08;只有第一层可以直接操作硬件&#xff0c;第二次只能使用第一层提供的功能接口..…

英语——语法——从句——状语从句——笔记

一、概念 状语从句&#xff08;Adverbial Clause&#xff09;是指句子用作状语时&#xff0c;起副词作用的句子。状语从句中的从句可以修饰谓语。 状语从句根据其作用可分为时间、地点、原因、条件、目的、结果、让步、方式和比较等九 种状语从句。状语从句一般由连词(从属连词…