diff --git a/Software/Assembler.java b/Software/Assembler.java
new file mode 100644
index 0000000000000000000000000000000000000000..500102ca05d413a5275653d391c05f77ecad01c5
--- /dev/null
+++ b/Software/Assembler.java
@@ -0,0 +1,406 @@
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class Assembler {
+	
+	private static List <JumpAddress> jumpAddressList;
+	private static BufferedWriter writer;
+	
+	public static void main(String[] args) throws IOException {		
+		
+		File source = new File(args[0]);
+		Scanner scannerOne = new Scanner(source);
+    	
+    	jumpAddressList = new ArrayList <JumpAddress> ();
+    	
+    	int position = 0;
+    	int address = 0;
+    	
+    	// TODO : Don't allow the same label twice!
+    	while(scannerOne.hasNextLine()) {
+    		String noComment = scannerOne.nextLine().split("#")[0];
+    		String line[] = noComment.trim().split("\\s+|,\\s+");
+    		
+    		if(line[0].equals("")) {
+    			continue;
+    		} else if(line[0].matches("\\w+:$")) {
+    			String labelName = line[0].substring(0, line[0].length() - 1);
+    			jumpAddressList.add(position, new JumpAddress(labelName, address * 2));
+    			position++;
+    		} else {
+    			address++;
+    		}
+    	}
+    	
+    	writer = new BufferedWriter(new FileWriter(args[1], false));
+        Scanner scannerTwo = new Scanner(source);
+        
+        address = 0;
+        
+        while(scannerTwo.hasNextLine()) {
+        	String noComment = scannerTwo.nextLine().split("#")[0];
+        	// alternative regular expression: "[\\s,]+"
+        	String line[] = noComment.trim().split("\\s+|,\\s+"); 
+        	String mnemonic = line[0];
+        	
+        	if(mnemonic.equals("")) {						// empty line
+        		continue;
+        	} else if(mnemonic.matches("[A-Za-z]*:$")) { 	// line containing a label
+    			continue;
+        	} else {  										// line containing an instruction  		   			
+    			switch(mnemonic) {
+    				// -----------------------------------------------------
+    				// -- ALU-Operations -----------------------------------
+    				// -----------------------------------------------------
+    				case "MOV":
+    					writeALUOp("00100000", line[1], line[2]);
+    					address++;
+    					break;
+    				case "ADDU":
+    					writeALUOp("00100001", line[1], line[2]);
+    					address++;
+    					break;
+    				case "ADDC":
+    					writeALUOp("00100010", line[1], line[2]);
+    					address++;
+    					break;
+       				case "SUBU":
+    					writeALUOp("00100011", line[1], line[2]);
+    					address++;
+    					break;
+       				case "AND":
+    					writeALUOp("00100100", line[1], line[2]);
+    					address++;
+    					break;
+       				case "OR":
+    					writeALUOp("00100101", line[1], line[2]);
+    					address++;
+    					break;
+       				case "XOR":
+    					writeALUOp("00100110", line[1], line[2]);
+    					address++;
+    					break;
+       				case "NOT":
+    					writeALUOp("00100111", line[1], "0000");
+    					address++;
+    					break;
+    	    		// -----------------------------------------------------
+    	    		// -- Shift-Operations ---------------------------------
+    	    		// -----------------------------------------------------
+     				case "LSL":
+    					writeShiftOp("00101000", line[1], line[2]);
+    					address++;
+    					break;
+     				case "LSR":
+    					writeShiftOp("00101001", line[1], line[2]);
+    					address++;
+    					break;
+     				case "ASR":
+    					writeShiftOp("00101010", line[1], line[2]);
+    					address++;
+    					break;
+     				case "LSLC":
+    					writeShiftOp("00101100", line[1], "0000");
+    					address++;
+    					break;
+    				case "LSRC":
+    					writeShiftOp("00101101", line[1], "0000");
+    					address++;
+    					break;
+    				case "ASRC":
+    					writeShiftOp("00101110", line[1], "0000");
+    					address++;
+    					break;
+    	    		// -----------------------------------------------------
+    	    		// -- Compare-Operations -------------------------------
+    	    		// -----------------------------------------------------
+      				case "CMPE":
+    					writeCompOp("00110000", line[1], line[2]);
+    					address++;
+    					break;
+      				case "CMPNE":
+    					writeCompOp("00110001", line[1], line[2]);
+    					address++;
+    					break;
+    				case "CMPGT":
+    					writeCompOp("00110010", line[1], line[2]);
+    					address++;
+    					break;
+    				case "CMPLT":
+    					writeCompOp("00110011", line[1], line[2]);
+    					address++;
+    					break;
+    	    		// -----------------------------------------------------
+    	    		// -- Immediate-Operations -----------------------------
+    	    		// -----------------------------------------------------
+    				case "MOVI":
+    					writeImmOp("00110100", line[1], line[2]);
+    					address++;
+    					break;
+    				case "ADDI":
+    					writeImmOp("00110101", line[1], line[2]);
+    					address++;
+    					break;
+    				case "SUBI":
+    					writeImmOp("00110110", line[1], line[2]);
+    					address++;
+    					break;
+       				case "ANDI":
+    					writeImmOp("00110111", line[1], line[2]);
+    					address++;
+    					break;
+       				case "LSLI":
+    					writeImmOp("00111000", line[1], line[2]);
+    					address++;
+    					break;
+     				case "LSRI":
+    					writeImmOp("00111001", line[1], line[2]);
+    					address++;
+    					break;
+     				case "BSETI":
+    					writeImmOp("00111010", line[1], line[2]);
+    					address++;
+    					break;
+     				case "BCLRI":
+    					writeImmOp("00111011", line[1], line[2]);
+    					address++;
+    					break;
+    	    		// -----------------------------------------------------
+    	    		// -- Memory-Operations --------------------------------
+    	    		// -----------------------------------------------------
+     				case "LDW":
+    					writeMemOp("0100", line[1], line[2], line[3]);
+    					address++;
+    					break;
+     				case "STW":
+    					writeMemOp("0101", line[1], line[2], line[3]);
+    					address++;
+    					break;
+        	    	// -----------------------------------------------------
+        	    	// -- Control-Flow-Operations --------------------------
+        	    	// -----------------------------------------------------
+     				case "BR":
+    					writeControlFlowOp("1000", line[1], address);
+    					address++;
+    					break;
+    				case "JSR":
+    					writeControlFlowOp("1001", line[1], address);
+    					address++;
+    					break;
+      				case "BT":
+    					writeControlFlowOp("1010", line[1], address);
+    					address++;
+    					break;
+      				case "BF":
+    					writeControlFlowOp("1011", line[1], address);
+    					address++;
+    					break;
+      				case "JMP":
+    					writeJMPOp("1100", line[1]);
+    					address++;
+    					break;
+            	    // -----------------------------------------------------
+            	    // -- Halt ---------------------------------------------
+            	    // -----------------------------------------------------
+      				case "HALT":
+    					writeHALTOp("1111");
+    					address++;
+    					break;
+    				default:
+    					// TODO: Throw exception, if no mnemonic matched!
+    			}
+    		}
+    	}
+        writer.close();
+        scannerTwo.close();
+        scannerOne.close();
+    }
+    
+    public static String regToBin(String register) {
+    	String output;
+    	
+    	switch(register) {
+    		case "R0":
+    			output = "0000";
+    			break;
+    		case "R1":
+    			output = "0001";
+    			break;
+    		case "R2":
+    			output = "0010";
+    			break;
+    		case "R3":
+    			output = "0011";
+    			break;
+    		case "R4":
+    			output = "0100";
+    			break;
+    		case "R5":
+    			output = "0101";
+    			break;
+    		case "R6":
+    			output = "0110";
+    			break;
+    		case "R7":
+    			output = "0111";
+    			break;
+    		case "R8":
+    			output = "1000";
+    			break;
+    		case "R9":
+    			output = "1001";
+    			break;
+    		case "R10":
+    			output = "1010";
+    			break;
+    		case "R11":
+    			output = "1011";
+    			break;
+    		case "R12":
+    			output = "1100";
+    			break;
+    		case "R13":
+    			output = "1101";
+    			break;
+    		case "R14":
+    			output = "1110";
+    			break;
+    		case "R15":
+    			output = "1111";
+    			break;
+    		default:
+    			// TODO: Throw exception, if no register matched!
+    			output = "0000";
+    	}
+    	
+    	return output;
+    }
+    
+	public static String hexToBin(String s) {
+		String hex = "";
+		
+		if(s.startsWith("0x")) {  
+			hex = s.substring(2, s.length());
+		} 
+		if(s.startsWith("$")) {
+			hex = s.substring(1, s.length());
+		}
+		
+		String bitstring = new BigInteger(hex, 16).toString(2);
+		StringBuffer extended = new StringBuffer(bitstring);
+		
+		for(int i = bitstring.length(); i < 4; i++) {
+			extended.insert(0, "0");
+    	}
+		
+		return extended.toString();
+	}
+	
+    public static void writeALUOp(String opCo, String rX, String rY) throws IOException {
+		writer.append(opCo);
+		writer.append(regToBin(rY));
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    public static void writeShiftOp(String opCo, String rX, String rY) throws IOException {
+		writer.append(opCo);
+		writer.append(regToBin(rY));
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    public static void writeCompOp(String opCo, String rX, String rY) throws IOException {
+		writer.append(opCo);
+		writer.append(regToBin(rY));
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    public static void writeImmOp(String opCo, String rX, String imm) throws IOException {
+		writer.append(opCo);
+		writer.append(hexToBin(imm));
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    public static void writeMemOp(String opCo, String rX, String rY, String offsetHex) throws IOException {
+    	String offsetBin = hexToBin(offsetHex);
+    	int offsetInt = Integer.parseInt(offsetBin, 2);
+    	
+    	if((offsetInt % 2) == 1 ) {
+    		// TODO: Throw exception, if invalid address is addressed!
+    	}
+    	
+    	if(offsetInt > 30) {
+    		// TODO: Throw exception, if invalid address is addressed!
+    	}
+    	
+    	String offset = offsetBin.substring(0, offsetBin.length()-1);
+		StringBuffer extended = new StringBuffer(offset);
+		
+		for(int i = offset.length(); i < 4; i++) {
+			extended.insert(0, "0");
+    	}
+    	
+    	String jumpAddressBinFixedLength = extended.toString();
+    	
+    	writer.append(opCo);
+		writer.append(jumpAddressBinFixedLength);
+		writer.append(regToBin(rY));
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    // TODO Throw exception, if label is not in jumpAddressList!
+    public static void writeControlFlowOp(String opCo, String label, int address) throws IOException {
+    	// PC = PC + 2 + imm12
+    	int byteAddress = 2 * (address + 1);
+    	
+    	int labelAddress = 0;
+    	for(int i = 0; i < jumpAddressList.size(); i++) {
+    		if(jumpAddressList.get(i).getLabel().equals(label)) {
+    			labelAddress = jumpAddressList.get(i).getAddress();
+    			break;
+    		}
+    	}
+    	
+    	int jumpAddressInt = labelAddress - byteAddress;
+    	String jumpAddressBin = Integer.toBinaryString(jumpAddressInt);
+    	String jumpAddressBinFixedLength;
+    	
+    	if(jumpAddressInt < 0) {
+    		jumpAddressBinFixedLength = jumpAddressBin.substring(jumpAddressBin.length()-12, jumpAddressBin.length());
+    	} else {
+    		StringBuffer extended = new StringBuffer(jumpAddressBin);
+    		for(int i = jumpAddressBin.length(); i < 12; i++) {
+    			extended.insert(0, "0");
+        	}
+    		jumpAddressBinFixedLength = extended.toString();
+    	}
+    	
+    	writer.append(opCo);
+		writer.append(jumpAddressBinFixedLength);
+        writer.append("\n");
+    }
+    
+    public static void writeJMPOp(String opCo, String rX) throws IOException {
+    	writer.append(opCo);
+    	writer.append("00000000");
+		writer.append(regToBin(rX));
+        writer.append("\n");
+    }
+    
+    public static void writeHALTOp(String opCo) throws IOException {
+    	writer.append(opCo);
+    	writer.append("000000000000");
+        writer.append("\n");
+    }
+}
+	
\ No newline at end of file