Java语言实现的Hack语言汇编编译器——加法器部分

最近在读《计算机系统要素》,看一些基础的东西。发现这本书如果大学学汇编前读那该多好,虽然有些部分难,但是浏览个大概还是可以的。读完就知道汇编这东西有什么用了。还有学模电也是如此,刚开始不知道那些与或门是哪里来的,也不知道有何用。


这本书前五章都在讲硬件平台的东西,从最基本的NAND门开始给你去构造其他的门。到布尔逻辑,自己构建加法器,输入选择器还有多位的选择器。接下来是时序逻辑的东西,关于时钟周期的。接下来是汇编语言,和8086的那个汇编有区别,但是很相似。基本就是把我大二大一学的东西连了一次。看到这本书的时候已经在毕业后了,所以,还没毕业的,如果你刚好看到我这篇东西,建议去读一下,即使不做每章的习题。我觉得过了一次之后还是大有益处。


书有个不好的地方在于一些习题的答案你虽然知道思路,却不知道表示方法。像数组那些。


这位同学写得很好,http://book.douban.com/review/7115224/


书的习题部分有一部分是一位芝加哥的比较年轻的老外写的,还有一些是这位网友写的。


而在第六章要自己写个汇编的编译器的时候,我就非常感兴趣了。毕竟编译原理没学过。而网友的Github代码是用Python实现。
然后我自己想了想,自己用Java实现一次吧。首先根据习题提供的加法的汇编文件,Add.asm进行基础的编译。


Hack是基于冯诺依曼架构的16位计算机。Hack语言包括两种指令:A-指令和C-指令。


具体表示什么就看书上的第四章吧。


基本的思路是。过滤掉//注释的代码。根据是A指令的标识@进行二进制转换。
根据C指令的形式也进行转换。
指令与二进制数有着特殊的额对应关系。


所以将其写进properties文件中。


Java部分代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

/**
 * @author Caikc
 * @description  
 * @date 2016-1-7 下午3:52:32
 * @company www.ewan.cn
 */
public class Assembly {
	/**
	 * get keyvalue from compile file
	 * @param key
	 * @return
	 * @throws IOException
	 */
	public static String getcompile(String key) throws IOException {
		InputStream ips = Assembly.class
				.getResourceAsStream("compile.properties");
		Properties p = new Properties();
		p.load(ips);
		/*
		 * Enumeration e = p.propertyNames(); while(e.hasMoreElements()){
		 * if(key.equals((String)e.nextElement())){
		 * System.out.println(p.get(key)); } }
		 */
		return (String) p.get(key);
	}
	public static String getdest(String key) throws IOException {
		InputStream ips = Assembly.class
				.getResourceAsStream("dest.properties");
		Properties p = new Properties();
		p.load(ips);
		return (String) p.get(key);
	}
	public static String getjump(String key) throws IOException {
		InputStream ips = Assembly.class
				.getResourceAsStream("jump.properties");
		Properties p = new Properties();
		p.load(ips);
		return (String) p.get(key);
	}

	 
	/**
	 * read lines of file   
	 * and replace the annotation
	 * @param filename
	 * @throws IOException
	 */
	public void getfile(String filename) throws IOException {
		BufferedReader bfr = new BufferedReader(new InputStreamReader(
				new FileInputStream(new File(filename))));
		String s = "";
		List<String> list = new ArrayList<String>();
		while ((s = bfr.readLine()) != null) {
			s = s.trim();
			int index = s.indexOf("//");
			if(!s.startsWith("//")&&!s.equals("")){
				if(index !=-1){
					s = s.substring(0,index);
				}
				list.add(s);
			}
		}
		for (String string : list) {
			//System.out.println(string);
			if(string.indexOf("@")!=-1){
				System.out.println(Assembly.tohexstring(string));
			}else{
				System.out.println(Assembly.compileCInstruction(string));
			}
		}
	}

	/**
	 * number to 16 bit binary string
	 * last bit 0 represent positive,1 represent negative.
	 * @ order compile to binary string 
	 * @param s
	 * @return
	 */
	public static String tohexstring(String s) {
		String hex = "";
		if(s.startsWith("@")){
			s=s.replace('@',' ').trim();

			String temp = Integer.toBinaryString(Integer.valueOf(s
					.replace('-', ' ').trim()));
			int n = temp.length();
			while (n < 16) {
				if (n == temp.length()) {
					if (Integer.valueOf(s) >= 0) {
						hex += "0";
					} else {
						hex += "1";
					}
				} else {
					hex += "0";
				}
				n += 1;
			}
			hex += temp;
		}else{
			hex = s;
		}
		
		return hex;
	}

	
	/**
	 * compile C 
	 * dest = comp;jump 
	 * dest and jump could be null,if dest is null,left out the =
	 * if jump is null, left out the ;
	 * 1 1 1 a c1-c6 d1-d3 j1-j3
	 * @throws IOException 
	 */
	public static String compileCInstruction(String line) throws IOException{
		String assembcode = "111";
		int indexdest = line.indexOf("=");
		int indexjump = line.indexOf(";");
		if(indexdest!=-1&&indexjump!=-1){
			String dest = line.substring(0,indexdest);
			String cmp= line.substring(indexdest,indexjump);
			String jmp = line.substring(indexjump+1,line.length());
			//System.out.println(dest+" "+cmp+" "+jmp);
			
			String cmpcode = Assembly.getcompile(cmp.trim());
			String destcode = Assembly.getdest(dest.trim());
			String jumpcode = Assembly.getjump(jmp.trim());
			
			assembcode = assembcode + cmpcode+destcode+jumpcode;
			
		}else if(indexdest!=-1&&indexjump==-1){
			String dest = line.substring(0,indexdest);
			String cmp = line.substring(indexdest+1,line.length());
			//System.out.println(dest+" "+cmp);
			
			String cmpcode = Assembly.getcompile(cmp.trim());
			String destcode = Assembly.getdest(dest.trim());
			//System.out.println("com:"+cmpcode);
			//System.out.println("dest:"+destcode);
			String jumpcode = "000";
			
			assembcode = assembcode + cmpcode+destcode+jumpcode;
			
		}else if(indexdest==-1&&indexjump!=-1){
			String jmp = line.substring(indexjump+1,line.length());
			//System.out.println(jmp);
			String cmpcode = "000000";
			String destcode = "000";
			String jumpcode = Assembly.getjump(jmp.trim());
			
			assembcode = assembcode + cmpcode+destcode+jumpcode;
		}
		return assembcode;
	}
	
	public static void main(String[] args) throws IOException {
		/*
		 * Assembly a = new Assembly(); try { a.get(); } catch (IOException e) {
		 * e.printStackTrace(); }
		 */
		//System.out.println(new Assembly().getcompile("0"));
		//System.out.println(new Assembly().tohexstring("9"));
		new Assembly()
				.getfile("C:/Users/Administrator/Desktop/nand2tetris (1)/nand2tetris/projects/06/add/Add.asm");
	}
}

compile.properties

0=0101010
1=0111111
-1=0111010
D=0001100
A=0110000
!D=0001101
!A=0110001
-D=0001111
-A=0110011
D+1=0011111
A+1=0110111
D-1=0001110
A-1=0110010
D+A=0000010
D-A=0010011
A-D=0000111
D&A=0000000
D|A=0010101
M=1110000,
!M=1110001
-M=1110011
M+1=1110111
M-1=1110010
D+M=1000010
D-M=1010011
M-D=1000111
D&M=1000000
D|M=1010101

dest.properties

null=000
M=001
D=010
MD=011
A=100
AM=101
AD=110
AMD=111

jump.properties

null=000
M=001
D=010
MD=011
A=100
AM=101
AD=110
AMD=111

最后的输出将Add.asm

// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/06/add/Add.asm

// Computes R0 = 2 + 3

@2
D=A //dgg
@3
D=D+A
@0
M=D

转换成二进制代码

0000000000000010
1110110000010000
0000000000000011
1110000010010000
0000000000000000
1110001100001000


由于写习题的时候还是有些题不懂,所以刚好加进了豆瓣的一个群。发现虽然群中的大家岁数都比较大。但是还是保持着对学习的兴趣。大家还一起用FPGA实现操作系统。想想要是我大二开始这样干,可能现在是一位嵌入式开发工程师也说不定。

相关文章
相关标签/搜索