COMP360 Assembler Write an assembler that reads the source code of an assembly program
(for an imaginary machine) and displays the machine language for that program. The following
assembler instructions must be supported. Instruction opcode Length Format Example add add
R1, R2, R3 sub R1, R2, R3 mult mult RI, R2, R3 I ld R1, addr R7) la R1, addr (RTT st R1, addr
R71 jump addr R71 R1, addr R71 3 push R1 Machine language instructions have the following
formats: 0: arithmetic Lopcode Reg I Reg 2 Reg3 4bits 4 bits 4 bits 1: Load, store. conditional
jump Dopcode eg index ad 4 bits 4 bits 4 bits 20 bits 2: call, jump de unused index addr 4 bits 4
bits 4 bits 20 bits 3: push, pop, lpsw. spsw opcode Reg 4 bits 4 bits 4: rtn opcode unused. 4 bits 4
bits
Solution
//First Create Package Collection then create all classes mentioned below
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package collection;
/**
*
* @author Rashmi Tiwari
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Assembler {
public static final String COMP_ADD = \"ADD\";
public static final String COMP_SUB = \"SUB\";
public static final String COMP_LOAD = \"LOAD\";
public static final String COMP_STORE = \"STORE\";
public static final String COMP_GOTO = \"GOTO\";
public static final String COMP_GOTOZ = \"GOTOZ\";
public static final String COMP_GOTOP = \"GOTOP\";
public static final String COMP_READ = \"READ\";
public static final String COMP_WRITE = \"WRITE\";
public static final String COMP_STOP = \"STOP\";
private static Map assemblyTable;
private static Map getAssemblyTable() {
if (assemblyTable == null) {
assemblyTable = new HashMap();
assemblyTable.put(COMP_ADD, Comp360Assembler.COMP_ADD);
assemblyTable.put(COMP_SUB, Comp360Assembler.COMP_SUB);
assemblyTable.put(COMP_LOAD, Comp360Assembler.COMP_LOAD);
assemblyTable.put(COMP_STORE, Comp360Assembler.COMP_STORE);
assemblyTable.put(COMP_GOTO, Comp360Assembler.COMP_GOTO);
assemblyTable.put(COMP_GOTOZ, Comp360Assembler.COMP_GOTOZ);
assemblyTable.put(COMP_GOTOP, Comp360Assembler.COMP_GOTOP);
assemblyTable.put(COMP_READ, Comp360Assembler.COMP_READ);
assemblyTable.put(COMP_WRITE, Comp360Assembler.COMP_WRITE);
assemblyTable.put(COMP_STOP, Comp360Assembler.COMP_STOP);
}
return assemblyTable;
}
public static int[] assemble(String program) throws Comp360ParsingException {
if (program == null) return null;
program = preProcess(program);
Map symTable = buildSymTable(program);
return translateCommands(program, symTable);
}
public static String preProcess(String text) throws Comp360ParsingException {
text = text.replaceAll(\"(?ms)\\\\/\\\\*.*?\\\\*\\\\/\", \"\");
text = text.replaceAll(\"(?m)\\\\/\\\\/.*$\", \"\");
text = text.replaceAll(\"(?m)#.*$\", \"\");
text = text.replaceAll(\"(?m)\'.*$\", \"\");
text = text.replaceAll(\"(?m)`.*$\", \"\");
re.
COMP360 Assembler Write an assembler that reads the source code of an.pdf
1. COMP360 Assembler Write an assembler that reads the source code of an assembly program
(for an imaginary machine) and displays the machine language for that program. The following
assembler instructions must be supported. Instruction opcode Length Format Example add add
R1, R2, R3 sub R1, R2, R3 mult mult RI, R2, R3 I ld R1, addr R7) la R1, addr (RTT st R1, addr
R71 jump addr R71 R1, addr R71 3 push R1 Machine language instructions have the following
formats: 0: arithmetic Lopcode Reg I Reg 2 Reg3 4bits 4 bits 4 bits 1: Load, store. conditional
jump Dopcode eg index ad 4 bits 4 bits 4 bits 20 bits 2: call, jump de unused index addr 4 bits 4
bits 4 bits 20 bits 3: push, pop, lpsw. spsw opcode Reg 4 bits 4 bits 4: rtn opcode unused. 4 bits 4
bits
Solution
//First Create Package Collection then create all classes mentioned below
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package collection;
/**
*
* @author Rashmi Tiwari
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Assembler {
public static final String COMP_ADD = "ADD";
public static final String COMP_SUB = "SUB";
public static final String COMP_LOAD = "LOAD";
public static final String COMP_STORE = "STORE";
public static final String COMP_GOTO = "GOTO";
public static final String COMP_GOTOZ = "GOTOZ";
2. public static final String COMP_GOTOP = "GOTOP";
public static final String COMP_READ = "READ";
public static final String COMP_WRITE = "WRITE";
public static final String COMP_STOP = "STOP";
private static Map assemblyTable;
private static Map getAssemblyTable() {
if (assemblyTable == null) {
assemblyTable = new HashMap();
assemblyTable.put(COMP_ADD, Comp360Assembler.COMP_ADD);
assemblyTable.put(COMP_SUB, Comp360Assembler.COMP_SUB);
assemblyTable.put(COMP_LOAD, Comp360Assembler.COMP_LOAD);
assemblyTable.put(COMP_STORE, Comp360Assembler.COMP_STORE);
assemblyTable.put(COMP_GOTO, Comp360Assembler.COMP_GOTO);
assemblyTable.put(COMP_GOTOZ, Comp360Assembler.COMP_GOTOZ);
assemblyTable.put(COMP_GOTOP, Comp360Assembler.COMP_GOTOP);
assemblyTable.put(COMP_READ, Comp360Assembler.COMP_READ);
assemblyTable.put(COMP_WRITE, Comp360Assembler.COMP_WRITE);
assemblyTable.put(COMP_STOP, Comp360Assembler.COMP_STOP);
}
return assemblyTable;
}
public static int[] assemble(String program) throws Comp360ParsingException {
if (program == null) return null;
program = preProcess(program);
Map symTable = buildSymTable(program);
return translateCommands(program, symTable);
}
public static String preProcess(String text) throws Comp360ParsingException {
text = text.replaceAll("(?ms)/*.*?*/", "");
text = text.replaceAll("(?m)//.*$", "");
text = text.replaceAll("(?m)#.*$", "");
text = text.replaceAll("(?m)'.*$", "");
text = text.replaceAll("(?m)`.*$", "");
3. return text;
}
private static int[] translateCommands(String program, Map symTable) throws
Comp360ParsingException {
ArrayList code = new ArrayList();
Scanner scan = new Scanner(program);
int lineNumber = 0;
int opNumber = 0;
while (scan.hasNextLine()) {
lineNumber++;
String line = scan.nextLine();
Scanner tokenizer = new Scanner(line);
if (!tokenizer.hasNext())
continue; // blank line
String token = tokenizer.next();
// IL position 2
if (isLineLabel(token)) {
if (!tokenizer.hasNext())
continue;
token = tokenizer.next();
}
// IL position 4
if (isInstruction(token)) {
token = token.toUpperCase();
Integer opCode = getAssemblyTable().get(token);
Integer address = 0;
if (!token.equals(COMP_STOP) && !token.equals(COMP_READ) &&
!token.equals(COMP_WRITE)) {
token = tokenizer.next();
if (!isNumber(token)) {
token = token.toUpperCase();
address = symTable.get(token);
} else {
address = Integer.parseInt(token);
4. }
}
code.add(opCode * 100 + address);
opNumber++;
}
}
return RunTools.deboxInteger(code);
}
public static Map buildSymbols(String program) throws Comp360ParsingException {
return buildSymTable(preProcess(program));
}
private static Map buildSymTable(String program) throws Comp360ParsingException {
Map lineLabels = new HashMap();
Map variables = new HashMap();
variables.put("ZERO", 98);
variables.put("ONE", 99);
Scanner scan = new Scanner(program);
int nextVariable = 50;
int lineNumber = 0;
int opNumber = 0;
while (scan.hasNextLine()) {
lineNumber++;
String line = scan.nextLine();
Scanner tokenizer = new Scanner(line);
if (!tokenizer.hasNext())
continue;
String token = tokenizer.next();
// IL position 2
if (isLineLabel(token)) {
token = token.substring(0, token.length() - 1);
if (lineLabels.get(token) != null)
throw new Comp360ParsingException("Duplicate line label "+token+"
encountered on line "+lineNumber);
5. lineLabels.put(token, opNumber);
if (!tokenizer.hasNext())
continue;
token = tokenizer.next();
}
// IL position 4
if (isInstruction(token)) {
token = token.toUpperCase();
if (!token.equals(COMP_STOP) && !token.equals(COMP_READ) &&
!token.equals(COMP_WRITE)) {
if (!tokenizer.hasNext())
throw new Comp360ParsingException("Unexpected end of line on line
"+lineNumber);
token = tokenizer.next();
if (!isNumber(token)) {
token = token.toUpperCase();
if (!variables.containsKey(token))
variables.put(token, nextVariable++);
} else {
int address = Integer.parseInt(token);
if (address > 99 || address < 0)
throw new Comp360ParsingException("Instruction addresses must be at most
two digits");
}
}
opNumber++;
if (!tokenizer.hasNext())
continue;
token = tokenizer.next();
}
throw new Comp360ParsingException("Expected end of line on line "+lineNumber);
}
if (opNumber > 49)
throw new Comp360ParsingException("Too many operations. Programs must have
fewer than 50 instructions");
if (nextVariable >= 98)
6. throw new Comp360ParsingException("Too many variables in program. Must be less
than 48");
variables.putAll(lineLabels); // line labels should have precedent over variables
return variables;
}
public static boolean isNumber(String token) {
try {
Integer.parseInt(token);
return true;
} catch (NumberFormatException e) {
return false;
}
}
public static boolean isInstruction(String token) {
return token != null && getAssemblyTable().containsKey(token.toUpperCase());
}
public static boolean isLineLabel(String token) {
return token != null && token.endsWith(":") && token.length() > 1;
}
public static boolean isSymbol(String token) {
return token.matches("^[a-zA-Z_][w]*$");
}
}
//Comp360Assembler class is in same package of Collection
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
7. */
package collection;
/**
*
* @author Rashmi Tiwari
*/
public interface Comp360Assembler extends Runnable{
public static final int DEFAULT_DATA = 0;
public static final int MIN_INT = -999;
public static final int MAX_INT = 999;
public static final int MEMORY_SIZE = 100;
public static final int PROGRAM_INSERTION_POINT = 0;
public static final int INSTRUCTION_SIZE = 1;
public static final int COMMAND = 0;
public static final int ADDRESS = 1;
public static final int COMP_STOP = 0;
public static final int COMP_ADD = 1;
public static final int COMP_SUB = 2;
public static final int COMP_LOAD = 3;
public static final int COMP_STORE = 4;
public static final int COMP_GOTO = 5;
public static final int COMP_GOTOZ = 6;
public static final int COMP_GOTOP = 7;
public static final int COMP_READ = 8;
public static final int COMP_WRITE = 9;
public void reset();
public void flushIO();
public String getBadStateReason();
public void fetch();
public int[] decode();
8. public void execute(int command, int address);
public void step();
public void run();
public boolean isRunning();
public int readOutput();
public void addInput(int data);
public int[] memDump();
public void loadMemDump(int memDump[]);
public int getIr();
public int getDr();
public int getPc();
}
//Custom Exception Class
package collection;
/**
*
* @author Rashmi Tiwari
*/
public class Comp360ParsingException extends Exception{
private static final long serialVersionUID = 1L;
public Comp360ParsingException(String message) {
super(message);
}
}
//Runner Class
/*
9. * To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package collection;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
*
* @author Rashmi Tiwari
*/
public class Runner {
/**
* Special output returned if a program timed out
*/
public static final int[] TIMED_OUT = {1000};
private static final long RUNNER_TIMEOUT = 10000;
public static int[] runProgram(Comp360Assembler comp360, int[] program, int[] input) {
program = RunTools.loadProgram(program);
comp360.reset();
comp360.flushIO();
comp360.loadMemDump(program);
for (int data : input)
comp360.addInput(data);
// run the program
Future programRunner = Executors.newSingleThreadExecutor().submit(comp360);
try {
programRunner.get(RUNNER_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException(e.getMessage(), e);
10. } catch (ExecutionException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (TimeoutException e) {
programRunner.cancel(true);
return TIMED_OUT.clone();
}
return RunTools.extractOutput(comp360);
}
}
//RunTool Class
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package collection;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
/**
*
* @author Rashmi Tiwari
*/
public class RunTools {
private static int[] blankMemory;
public static int[] loadProgram(int[] program) {
if (program == null)
return getBlankMemory().clone();
if (program.length == Comp360Assembler.MEMORY_SIZE)
return program; // no need to load it into a memory dump
if (program.length > Comp360Assembler.MEMORY_SIZE)
11. return null;
int[] newProgram = getBlankMemory().clone();
System.arraycopy(program, 0, newProgram, 0, program.length);
return newProgram;
}
public static int[] extractOutput(Comp360Assembler comp360) {
List outputList = new LinkedList();
while (true) {
try {
outputList.add(comp360.readOutput());
} catch (NoSuchElementException e) {
// finished reading output
break;
}
}
return deboxInteger(outputList);
}
private static int[] getBlankMemory() {
if (blankMemory == null) {
blankMemory = new int[Comp360Assembler.MEMORY_SIZE];
Arrays.fill(blankMemory, 0);
blankMemory[98] = 0; // write-protected constant
blankMemory[99] = 1; // write-protected constant
}
return blankMemory;
}
static int[] deboxInteger(List a) {
if (a == null) return null;
int[] result = new int[a.size()];
Iterator iter = a.iterator();
for (int i = 0; i < result.length; i++) {
12. result[i] = iter.next();
}
return result;
}
}
//Core Class
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package collection;
import java.util.Arrays;
import java.util.LinkedList;
/**
*
* @author Rashmi Tiwari
*/
public class Core {
private static final int DIGITS = 3;
private int[] mem;
private int ir;
private int dr;
private int pc;
private LinkedList stdin;
private LinkedList stdout;
private String badState;
private boolean running;
/**
* Constructs a new VIC object with default state
*/
public Core() {
stdin = new LinkedList();
stdout = new LinkedList();
mem = new int[Comp360Assembler.MEMORY_SIZE];
13. reset();
resetMemory();
flushIO();
}
public void reset() {
pc = Comp360Assembler.PROGRAM_INSERTION_POINT;
ir = Comp360Assembler.DEFAULT_DATA;
dr = Comp360Assembler.DEFAULT_DATA;
badState = null;
running = false;
}
private void resetMemory() {
Arrays.fill(mem, 0);
mem[98] = 0; // write protected constants ZERO & ONE
mem[99] = 1;
}
private boolean inBadState() {
return badState != null;
}
public void fetch() {
if (inBadState())
return;
ir = mem[pc];
pc += Comp360Assembler.INSTRUCTION_SIZE;
}
public int[] decode() {
if (inBadState())
return null;
if (!isProperInstruction(ir)) {
badState("Malformed Instruction at " + pc + ":" + ir);
return null;
}
// extract the nth digit of the IR, and dispatch it with the rest of the digits
14. int decode[] = new int[2];
decode[Comp360Assembler.COMMAND] = extractDigitN(ir, DIGITS);
decode[Comp360Assembler.ADDRESS] = ir % (int) (Math.pow(10, DIGITS - 1));
return decode;
}
private boolean isProperInstruction(int ir) {
return Comp360Assembler.MAX_INT >= ir && ir >= 0;
}
private int extractDigitN(int data, int n) {
return (data / (int) (Math.pow(10, n - 1))) % 10;
}
public void execute(int command, int address) {
if (inBadState())
return;
switch (command) {
case Comp360Assembler.COMP_STOP:
running = false;
break;
case Comp360Assembler.COMP_ADD:
if (!isValidData(dr + mem[address]))
badState("Integer Overflow at " + pc + ":" + ir);
dr += mem[address];
break;
case Comp360Assembler.COMP_SUB:
if (!isValidData(dr - mem[address]))
badState("Integer underflow at " + pc + ":" + ir);
dr -= mem[address];
break;
case Comp360Assembler.COMP_LOAD:
dr = mem[address];
break;
case Comp360Assembler.COMP_STORE:
if (address == 98 || address == 99)
badState("Memory address "+address+" is write protected at "+pc+":"+ir);
mem[address] = dr;
15. break;
case Comp360Assembler.COMP_GOTO:
pc = address;
break;
case Comp360Assembler.COMP_GOTOZ:
if (dr == 0) {
pc = address;
}
break;
case Comp360Assembler.COMP_GOTOP:
if (dr > 0) {
pc = address;
}
break;
case Comp360Assembler.COMP_READ:
dr = readInput();
break;
case Comp360Assembler.COMP_WRITE:
stdout.add(dr);
break;
default:
badState("Bad VIC instruction: " + command + address);
}
}
private int readInput() {
if (!stdin.isEmpty())
return stdin.remove();
else {
badState("No more input at " + pc);
return Comp360Assembler.DEFAULT_DATA;
}
}
private void badState(String reason) {
running = false;
badState = reason;
16. }
public String getBadStateReason() {
return this.badState;
}
public void step() {
if (inBadState())
return;
fetch();
int decode[] = decode();
execute(decode[Comp360Assembler.COMMAND],
decode[Comp360Assembler.ADDRESS]);
}
public void run() {
running = true;
while (running && !inBadState()) {
step();
}
}
public void addInput(int data) {
if (isValidData(data))
stdin.add(data);
}
private boolean isValidData(int data) {
return Comp360Assembler.MAX_INT >= data && data >=
Comp360Assembler.MIN_INT;
}
public int readOutput() {
return stdout.remove();
}
public int[] memDump() {
return mem.clone();
17. }
public void loadMemDump(int memDump[]) {
if (memDump.length != Comp360Assembler.MEMORY_SIZE)
return; // not a proper memdump
for (int i = 0; i < Comp360Assembler.MEMORY_SIZE; i++)
if (!isValidData(memDump[i])) {
return; // not a proper memdump
}
// NOTE: ignores the last 2 cells in the mem-dump since they are
// supposed to be constant, write protected cells.
System.arraycopy(memDump, 0, mem, 0, Comp360Assembler.MEMORY_SIZE - 2);
}
public int getIr() {
return ir;
}
public int getDr() {
return dr;
}
public int getPc() {
return pc;
}
public void flushIO() {
stdin.clear();
stdout.clear();
}
public boolean isRunning() {
return running;
}
protected void setDr(int dr) {
this.dr = dr;
}
}