From f0a24379752d1b27f54a065339fc18327d4fad6e Mon Sep 17 00:00:00 2001 From: Quazi Irfan GD Date: Sun, 13 Nov 2016 18:25:42 -0600 Subject: [PATCH] Everything except Format 4 and M record --- src/Assembler/Main.java | 97 +++++--- src/Assembler/OpcodeUtility.java | 16 +- src/Assembler/Pass1Utility.java | 93 +++----- src/Assembler/Pass2Utility.java | 319 ++++++++++++++++++++++++++ src/Assembler/Utility.java | 71 ++++++ src/OperandPkg/Operand.java | 8 +- src/OperandPkg/OperandUtility.java | 57 +++-- src/SymbolPkg/Node.java | 2 +- src/SymbolPkg/SymbolTable.java | 3 +- src/SymbolPkg/SymbolTableUtility.java | 18 -- 10 files changed, 546 insertions(+), 138 deletions(-) create mode 100644 src/Assembler/Pass2Utility.java diff --git a/src/Assembler/Main.java b/src/Assembler/Main.java index 67b2353..dbdb18d 100644 --- a/src/Assembler/Main.java +++ b/src/Assembler/Main.java @@ -1,6 +1,7 @@ package Assembler; import OperandPkg.Literal; +import OperandPkg.OperandUtility; import SymbolPkg.*; import java.io.*; @@ -11,12 +12,12 @@ // ASSIGNMENT : 3 // DUE DATE : 11/4/16 // INSTRUCTOR : Dr. Hamer -// DESCRIPTION : Assignment 3 +// DESCRIPTION : Assignment 4 /** - * Assembler.Main is the Entry point of Assignment 3 : Pass 1 + * Assembler.Main is the Entry point of Assignment 4 : Pass 2 * - * Thic class checks if the SIC Assembly source was supplied via command line. + * Input : Intermediate file(file format ending with .int) created from assignment 1 * If not then the program requests a file name. If file not found, the program terminates. * If found, a static method from Pass1Utility class is called. The last parameter of this method is the output file name. * We process every instruction, and print output of Pass 1 in that file. @@ -25,44 +26,78 @@ public class Main { public static void main(String[] args) throws IOException{ SymbolTable symbolTable = new SymbolTable(); - LinkedList literalLnkdLst = new LinkedList<>(); - - // set input files - String inputFile; - if(args.length < 1){ - System.out.println("Missing command like argument."); - - // request the intput SIC/XE Assembly file - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - System.out.print("Enter SIC Assembly file : "); - inputFile = reader.readLine(); - } else { - inputFile = args[0]; - } - - -// Pass1Utility.populateIntermediateFile(inputFile, symbolTable, literalLnkdLst); - Pass1Utility.populateIntermediateFile("A3_1.txt", symbolTable, literalLnkdLst); - System.out.println("************************************************************"); - Pass1Utility.populateIntermediateFile("A3_2.txt", symbolTable, literalLnkdLst); - System.out.println("************************************************************"); - Pass1Utility.populateIntermediateFile("A3_3.txt", symbolTable, literalLnkdLst); - System.out.println("************************************************************"); - Pass1Utility.populateIntermediateFile("A3_4.txt", symbolTable, literalLnkdLst); + LinkedList literalTable = new LinkedList<>(); // // Populate Symbol Table -// SymbolTableUtility.populateSymbolTable(symbolTable, "A2_labels.txt"); // System.out.println("*** SYMBOL TABLE ***\nSymbol\t Value\t rflag\t iflag\t mflag\t"); +// BufferedReader symbolReader = new BufferedReader(new FileReader("OldTestFiles/A2_labels.txt")); +// String symbolLine = symbolReader.readLine(); +// while(symbolLine != null){ +// symbolTable.addLine(symbolLine); +// symbolLine = symbolReader.readLine(); +// } // symbolTable.view(); // // // Evaluate and print Expressions // System.out.println("\n*** EXPRESSIONS ***\nExpresion\t\t Value\t Relocatable n i x"); -// OperandUtility.evaluateOperand(symbolTable, literalLnkdLst, "A2_operands.txt"); -// +// BufferedReader operandReader = new BufferedReader(new FileReader("OldTestFiles/A2_operands.txt")); +// String operandLine = operandReader.readLine(); +// while(operandLine != null) { +// OperandUtility.evaluateOperand(symbolTable, literalTable, operandLine); +// operandLine = operandReader.readLine(); +// } + + String inputFile = "CS_Func.txt"; + Pass1Utility.populateTableGenerateInt(inputFile, symbolTable, literalTable); + + // print the symbol table and literal table + System.out.println("> Symbol Value\trflag\tiflag\tmflag"); + + // TODO are the relocaability of registers are false? Does it matter? + symbolTable.addLine("A 0 false"); + symbolTable.addLine("X 1 false"); + symbolTable.addLine("L 2 false"); + symbolTable.addLine("B 3 false"); + symbolTable.addLine("S 4 false"); + symbolTable.addLine("T 5 false"); + symbolTable.addLine("F 6 false"); + symbolTable.addLine("PC 8 false"); + symbolTable.addLine("SW 9 false"); + + symbolTable.view(); + System.out.println("\n> literal\tValue\tlength\taddress"); + for(Literal l : literalTable) + System.out.println(l); + + System.out.println("\n> Generated Object code"); + Pass2Utility.generateObj(inputFile, symbolTable, literalTable); + +// Pass1Utility.populateTableGenerateInt("A3_1.txt", symbolTable, literalTable); +// System.out.println("************************************************************"); +// Pass1Utility.populateTableGenerateInt("A3_2.txt", symbolTable, literalTable); +// System.out.println("************************************************************"); +// Pass1Utility.populateTableGenerateInt("A3_3.txt", symbolTable, literalTable); +// System.out.println("************************************************************"); +// Pass1Utility.populateTableGenerateInt("A3_4.txt", symbolTable, literalTable); + + // // Print contents of the literal table // System.out.println("\n*** LITERAL TABLE ***\nName\t\t Value\t\t Size\t Address"); -// for(Object o : literalLnkdLst){ +// for(Object o : literalTable){ // System.out.println(o); +// } + +// // set input files +// String inputFile; +// if(args.length < 1){ +// System.out.println("Missing command like argument."); +// +// // request the intput SIC/XE Assembly file +// BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); +// System.out.print("Enter SIC Assembly Intermediate file : "); +// inputFile = reader.readLine(); +// } else { +// inputFile = args[0]; // } } } diff --git a/src/Assembler/OpcodeUtility.java b/src/Assembler/OpcodeUtility.java index 94890ad..c5333dd 100644 --- a/src/Assembler/OpcodeUtility.java +++ b/src/Assembler/OpcodeUtility.java @@ -17,6 +17,12 @@ public class OpcodeUtility { * @return Returns opcode if found from instructions.txt, or returns -1 */ public static int getFormat(String opcode){ + boolean format4 = false; + if(opcode.contains("+")) { + format4 = true; + opcode = opcode.substring(1); + } + try(BufferedReader inputReader = new BufferedReader(new FileReader("instructions.txt"))){ String instruction = inputReader.readLine(); StringTokenizer tokenizer; @@ -24,7 +30,11 @@ public static int getFormat(String opcode){ tokenizer = new StringTokenizer(instruction, " "); if(tokenizer.hasMoreTokens()){ if(tokenizer.nextToken().equals(opcode)){ - return Integer.parseInt(tokenizer.nextToken()); + // if opcode found fetch the second column or return 4 if format4 is true + if(format4) + return 4; + else + return Integer.parseInt(tokenizer.nextToken()); } } instruction = inputReader.readLine(); @@ -42,6 +52,9 @@ public static int getFormat(String opcode){ * @return Returns Hex code as String if found from instructions.txt, or returns null */ public static String getHexCode(String opcode){ + if(opcode.contains("+")) + opcode = opcode.substring(1); + try(BufferedReader inputReader = new BufferedReader(new FileReader("instructions.txt"))){ String instruction = inputReader.readLine(); StringTokenizer tokenizer; @@ -49,6 +62,7 @@ public static String getHexCode(String opcode){ tokenizer = new StringTokenizer(instruction, " "); if(tokenizer.hasMoreTokens()){ if(tokenizer.nextToken().equals(opcode)){ + // if opcode found fetch the third column tokenizer.nextToken(); return tokenizer.nextToken(); } diff --git a/src/Assembler/Pass1Utility.java b/src/Assembler/Pass1Utility.java index 469ec70..df8a9ec 100644 --- a/src/Assembler/Pass1Utility.java +++ b/src/Assembler/Pass1Utility.java @@ -15,18 +15,19 @@ public class Pass1Utility { public static int startAddress = 0; public static int LineCounter = startAddress; // both startAddress and LineCounter will change if START directive is found + public static int programLength = 0; - public static void populateIntermediateFile( - String assemblyFileName, SymbolTable symbolTable, LinkedList literalLnkdLst) + public static void populateTableGenerateInt( + String assemblyFileName, SymbolTable symbolTable, LinkedList literalTable) throws IOException { // set the output file name, and set a output writer to write on that file String intermediateFileName = assemblyFileName.substring(0, assemblyFileName.indexOf('.')).concat(".int"); - PrintWriter outputWriter = new PrintWriter(intermediateFileName, "UTF-8"); + PrintWriter writer = new PrintWriter(intermediateFileName, "UTF-8"); // Take input and process SIC Instruction - BufferedReader inputReader = new BufferedReader(new FileReader(assemblyFileName)); - String instruction = inputReader.readLine(); + BufferedReader reader = new BufferedReader(new FileReader(assemblyFileName)); + String instruction = reader.readLine(); String label, opcode, operand; int format = 0; @@ -50,14 +51,12 @@ public static void populateIntermediateFile( // After comment removal if there is no token, read the next line StringTokenizer tokenizer = new StringTokenizer(instruction); if(tokenizer.countTokens() == 0){ - instruction = inputReader.readLine(); + instruction = reader.readLine(); continue; } - // Make everything upper case in input instruction - // read label Node symbol = null; // if first character is a white space then there is no label @@ -79,14 +78,8 @@ public static void populateIntermediateFile( symbol.rflag = false; // format 3 or format 4 opcode - if(opcode.charAt(0) == '+'){ - format = 4; - LineCounter += format; - } else { - format = OpcodeUtility.getFormat(opcode); - LineCounter += format; - } - + format = OpcodeUtility.getFormat(opcode); + LineCounter += format; } // read operand @@ -104,11 +97,11 @@ public static void populateIntermediateFile( symbol.rflag = true; } else { // Evaluate the operand - OperandUtility.evaluateOperand(symbolTable, literalLnkdLst, operand); + OperandUtility.evaluateOperand(symbolTable, literalTable, operand); } } - // Handles BYTE/WORD operand + // Handles BYTE operand if(opcode.equals("BYTE")){ String temp = operand.substring(operand.indexOf('\'')+1, operand.lastIndexOf('\'')); if(operand.contains("C")) @@ -119,6 +112,12 @@ public static void populateIntermediateFile( LineCounter += format; } + // Handles WORD operand + if(opcode.equals("WORD")){ + format = 3; + LineCounter += format; + } + // Handles RESW operand if(opcode.equals("RESW")){ format = 3 * Integer.parseInt(operand); @@ -132,66 +131,48 @@ public static void populateIntermediateFile( } // generate the intermediate instruction - String intermediateInstruction = String.format("%-10s %-10s %-10s %-10s", - padHexString(LineCounter-format), + String intermediateInstruction = String.format("%-15s%-15s%-15s%-15s", + Utility.pad(LineCounter-format, 5), ((label == null) ? " " : label ), ((opcode == null) ? " " : opcode ), ((operand == null) ? " " : operand)); - // print the intermediate instruction to file - outputWriter.println(intermediateInstruction); - + // print the intermediate instruction to terminal and file System.out.println(intermediateInstruction); + writer.println(intermediateInstruction); + // print the intermediate instruction to terminal - instruction = inputReader.readLine(); + instruction = reader.readLine(); } // add the literal lists at the end of the program and update the address of the literals - for(Literal literal : literalLnkdLst){ - String intermediateInstruction = String.format("%-10s * %-10s", padHexString(LineCounter-format), literal.name); + for(Literal literal : literalTable){ + String intermediateInstruction = String.format("%-15s* %-15s", Utility.pad(LineCounter-format, 5), literal.name); + System.out.println(intermediateInstruction); + writer.println(intermediateInstruction); + literal.address = LineCounter-format; LineCounter += literal.length; } // Print the program langth; LineCounter is always updated - System.out.println("Program Length : " + Integer.toHexString(LineCounter).toUpperCase()); +// System.out.println("Program Length : " + Integer.toHexString(LineCounter).toUpperCase()); + programLength = LineCounter; // close the intermediate file - outputWriter.close(); + writer.close(); // print the populated symbol table - System.out.println("\n *** Symbol Table : (Symbol Value Rflag Iflag Mflag)"); - symbolTable.view(); +// System.out.println("\n *** Symbol Table : (Symbol Value Rflag Iflag Mflag)"); +// symbolTable.view(); // print the populated literal tbale - System.out.println("\n *** Literal Table : (Literal HexValue Length Address)"); - for(Object o : literalLnkdLst){ - System.out.println(o); - } +// System.out.println("\n *** Literal Table : (Literal HexValue Length Address)"); +// for(Object o : literalTable){ +// System.out.println(o); +// } } - private static String padHexString(int lineCounter){ - int padCount; - - if(lineCounter >= 16 & lineCounter < 255) // More than F, Pad '00010' - padCount = 3; - else if(lineCounter >= 255 & lineCounter < 4095) // More than FF, Pad '00100' - padCount = 2; - else if(lineCounter >= 4095) // More than FFF, Pad '01000' - padCount = 1; - else - padCount = 4; // Single character, Pad '00001' - - // add zero's - StringBuilder sb = new StringBuilder(); - for(int i=0; i literalTable) throws IOException{ + inputFile = inputFile.substring(0, inputFile.indexOf('.')).concat(".int"); + + BufferedReader reader = new BufferedReader(new FileReader(inputFile)); + String instruction = reader.readLine(); + while (instruction != null){ + String objectCode = ""; + String[] fields = getFields(instruction); + + // if field[1] starts with * we have rached the literal dump section + if(fields[1] != null && fields[1].equals("*")){ + instruction = reader.readLine(); + continue; + } + + if(fields[2].equals("START")){ + System.out.println(instruction + " " + "H^" + Utility.pad(fields[1]) +"^" + Utility.pad(Pass1Utility.startAddress, 6) +"^"+ + Utility.pad(Pass1Utility.programLength, 6));// printing objectcode + instruction = reader.readLine(); + continue; + } + + if(fields[2].equals("BASE") | fields[2].equals("EQU") | fields[2].equals("RESB") | fields[2].equals("RESW")){ + // terminate and dump pending t records, and start a new t record + System.out.println(instruction + " -"); // printing objectcode + instruction = reader.readLine(); + continue; + } + + // handle EXTDEF and EXTREF + if(fields[2].equals("EXTDEF")){ + System.out.print(instruction + " " + "D"); // printing objectcode + StringTokenizer tokenizer = new StringTokenizer(fields[3], ", "); + while(tokenizer.hasMoreTokens()){ + String symbolName = tokenizer.nextToken(); + int symbolValue = symbolTable.search(symbolName).getValue(); + objectCode = objectCode.concat("^").concat(Utility.pad(symbolName)).concat("^").concat(Utility.pad(symbolValue, 6)); + } + System.out.println(objectCode); // printing objectcode + instruction = reader.readLine(); + continue; + } else if(fields[2].equals("EXTREF")){ + System.out.print(instruction + " " + "R"); // printing objectcode + + StringTokenizer tokenizer = new StringTokenizer(fields[3], ","); + while (tokenizer.hasMoreTokens()){ + String symbolName = tokenizer.nextToken(); + Node externalSymbol = new Node(symbolName); + externalSymbol.value = 0; + externalSymbol.rflag = false; + externalSymbol.iflag = false; + externalSymbol.mflag = false; // redundant because default initializer + symbolTable.add(externalSymbol); + + objectCode = objectCode.concat("^").concat(Utility.pad(symbolName)); + } + System.out.println(objectCode); // printing objectcode + instruction = reader.readLine(); + continue; + } + + // handle BYTE C'abc' + if(fields[2].equals("BYTE")){ + if(fields[3].contains("C'")){ + // generate the object code + fields[3] = fields[3].substring(fields[3].indexOf("'")+1, fields[3].lastIndexOf("'")); + String charHexValue = ""; + for(int i = 0; i literalTable, String literalExpression){ + literalExpression = literalExpression.substring(1); + + for(Literal literal : literalTable){ + if(literal.name.equals(literalExpression)) + return literal.address; + } + + return -1; + } + + private static int getNextLineCounter(int currentLineCounter, String opcode, String operand){ + int opcodeFormat = OpcodeUtility.getFormat(opcode); + + // handle LDA STA + if(opcodeFormat != 0){ + return currentLineCounter + opcodeFormat; + } + + // handle BYTE, WORD, RESB, RESW + else { + if(opcode.equals("BYTE")){ + String temp = operand.substring(operand.indexOf('\'')+1, operand.lastIndexOf('\'')); + if(operand.contains("C")) + return currentLineCounter + temp.length(); + else + return currentLineCounter + temp.length() / 2; + } + + else if(opcode.equals("RESW")){ + return currentLineCounter + 3 * Integer.parseInt(operand); + } + + else if(opcode.equals("RESB")){ + return currentLineCounter + Integer.parseInt(operand); + } + } + + return currentLineCounter; + } +} diff --git a/src/Assembler/Utility.java b/src/Assembler/Utility.java index 22d85aa..08251fe 100644 --- a/src/Assembler/Utility.java +++ b/src/Assembler/Utility.java @@ -58,4 +58,75 @@ public static boolean isHex(String s) { // only got here if we didn't return false return true; } + + /** + * Given decimal number this fucntion will return a left padded hex number of given length. + * Requesting padding of a number that can't be accomodated with the length will return wrong value. + * @param decimalValue The decimal value we need to pad + * @param length The desired length + * @return Returns the hex value of the decimal number with left padded with zero. + */ + + public static String pad(int decimalValue, int length){ + int padCount; + + if(decimalValue < 0){ + String negHexValue = Integer.toHexString(decimalValue); + String resizedHexValue = negHexValue.substring(negHexValue.length()-length, negHexValue.length()); // fffffc > ffc + return resizedHexValue.toUpperCase(); + } + + // when hex value is within 10 and FF (inclusive) + if(decimalValue >= 16 && decimalValue <= 255) + padCount = length - 2; + + // when hex value is within 100 and FFF (inclusive) + else if(decimalValue >= 256 && decimalValue <= 4095) + padCount = length - 3; + + // when hex value is within 1000 and FFFF (inclusive) + else if(decimalValue >= 4096 && decimalValue <= 65535) + padCount = length - 4; + + // when hex value is within 0 and F + else + padCount = length - 1; + + // add zero's + StringBuilder sb = new StringBuilder(); + for(int i=0; i 4 + else if(s.length() > 4) { + return s.substring(0, 4); + } + + // if label size = 4 + else { + return s; + } + } } diff --git a/src/OperandPkg/Operand.java b/src/OperandPkg/Operand.java index d3e63fc..76686d2 100644 --- a/src/OperandPkg/Operand.java +++ b/src/OperandPkg/Operand.java @@ -6,7 +6,7 @@ public class Operand { public String expression; public int value; - public boolean relocability, nbit, ibit, xbit; + public boolean relocability, Nbit, Ibit, Xbit; // default to false public boolean errorflag; public boolean errorStatus; @@ -19,9 +19,9 @@ public String toString() { expression, value, (relocability ? "Relative":"Absolute"), - (nbit? "1":"0"), - (ibit? "1":"0"), - (xbit? "1":"0")); + (Nbit ? "1":"0"), + (Ibit ? "1":"0"), + (Xbit ? "1":"0")); return output; } diff --git a/src/OperandPkg/OperandUtility.java b/src/OperandPkg/OperandUtility.java index f91c03d..42b4205 100644 --- a/src/OperandPkg/OperandUtility.java +++ b/src/OperandPkg/OperandUtility.java @@ -14,15 +14,20 @@ */ public class OperandUtility{ private static String original; + public static Operand operand; + public static Literal literal; /** * This method does the initial Expression evalution. * * @param symbolTable Take the symbol table to compare the Exparesions with - * @param literalLnkdLst Holds the Linked link populated with literals + * @param literalTable Holds the Linked link populated with literals * @param expression operand to be evaluated */ - public static String evaluateOperand(SymbolTable symbolTable, LinkedList literalLnkdLst, String expression) throws IOException{ + public static String evaluateOperand(SymbolTable symbolTable, LinkedList literalTable, String expression) throws IOException{ + operand = new Operand(); + literal = new Literal(); + if(expression != null && expression.length() > 0){ // original string hold the unaltered expression original = expression; @@ -33,31 +38,32 @@ public static String evaluateOperand(SymbolTable symbolTable, LinkedList 1 + && + ((expression.charAt(0) == '+' | expression.charAt(0) == '-') & Character.isDigit(expression.charAt(1)))){ // for +6 or -6 - operand.nbit = false; - operand.ibit = true; + operand.Nbit = false; + operand.Ibit = true; } else { // for expression OR expression+expression - // but for literal + literal nbit and ibit has to be set 0 and 1 - operand.nbit = true; - operand.ibit = true; + // but for literal + literal Nbit and Ibit has to be set 0 and 1 + operand.Nbit = true; + operand.Ibit = true; } // checks for expression,X @@ -68,7 +74,7 @@ public static String evaluateOperand(SymbolTable symbolTable, LinkedList