-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMain.java
More file actions
285 lines (241 loc) · 11.6 KB
/
Main.java
File metadata and controls
285 lines (241 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
package com.example;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents a simple assembler with two passes to process SIC/XE assembly language programs.
* It generates a Symbol Table, Location Table, and Object Code for each input file.
*/
public class Main {
// Data structures to store symbol table, location table, and operation codes
private Map<String, Integer> symTable = new HashMap<>();
private Map<String, Integer> locTable = new HashMap<>();
private Map<String, Integer> optab = new HashMap<>();
// Program counters and lengths
private int locCounter = 0;
private int programLength = 0;
// Flags for processing literals
private boolean inLiteral = false;
private int literalLength = 0;
/**
* Main method to execute the assembler for a set of input files.
*
* @param args Command line arguments (not used in this implementation).
*/
public static void main(String[] args) {
// Create an instance of the assembler
Main assembler = new Main();
// Input files to process
String[] inputFiles = {"basic.txt", "functions.txt", "literals.txt", "control_section.txt", "macros.txt", "prog_blocks.txt"};
// Process each input file
for (String inputFileName : inputFiles) {
try {
// Execute pass 1 and pass 2
assembler.pass1(inputFileName);
assembler.pass2(inputFileName, "output.obj");
// Display tables after processing each input file
assembler.displayTables(inputFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Pass 1 of the assembler: Build Symbol and Location Tables.
*
* @param inputFileName Input file containing SIC/XE assembly code.
* @throws IOException If an I/O error occurs while reading the input file.
*/
private void pass1(String inputFileName) throws IOException {
// Open the input file for reading
BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
String line;
// Flags to track control sections and program blocks
boolean inControlSection = false;
String currentControlSection = "";
boolean inProgramBlock = false;
String currentProgramBlock = "";
// Process each line in the input file
while ((line = reader.readLine()) != null) {
// Split the line into tokens
String[] tokens = line.split("\\s+");
// Skip empty lines
if (tokens.length == 0) {
continue;
}
// Extract label and opcode
String label = tokens[0];
String opcode = (tokens.length > 1) ? tokens[1] : "";
// Process labels and symbols
if (!label.isEmpty()) {
// Prepend control section or program block name to the label if applicable
if (inControlSection) {
label = currentControlSection + "." + label;
} else if (inProgramBlock) {
label = currentProgramBlock + "." + label;
}
// Build the symbol table
symTable.put(label, locCounter);
}
// Determine program length and update location counter based on opcodes
if (opcode.equals("END")) {
programLength = locCounter;
inControlSection = false;
}
// Update location counter based on opcodes
if (opcode.equals("CSECT")) {
locCounter = 0; // Start of a new control section
inControlSection = true;
currentControlSection = label;
} else if (opcode.equals("USE")) {
// Start of a program block
inProgramBlock = true;
currentProgramBlock = (tokens.length > 2) ? tokens[2] : "";
} else if (opcode.equals("ENDUSE")) {
// End of a program block
inProgramBlock = false;
currentProgramBlock = "";
} else if (opcode.equals("RESW") || opcode.equals("RESB")) {
int operandValue = (tokens.length > 2) ? Integer.parseInt(tokens[2]) : 0;
locCounter += (opcode.equals("RESW")) ? 3 * operandValue : operandValue;
} else if (opcode.equals("BYTE")) {
// Handle BYTE directive
inLiteral = true;
String literalValue = (tokens.length > 2) ? tokens[2] : "";
literalLength = (literalValue.startsWith("X'")) ? (literalValue.length() - 3) / 2 : (literalValue.length() - 3);
locCounter += literalLength;
} else if (opcode.equals("MEND")) {
// End of macro definition (no action in pass 1)
} else if (inProgramBlock) {
// Process program block instructions (no action in pass 1)
} else if (opcode.equals("START")) {
// Set starting address for the program
locCounter = (tokens.length > 2) ? Integer.parseInt(tokens[2], 16) : 0;
} else {
// Update location counter based on standard instructions
locCounter += (opcode.startsWith("+")) ? 4 : 3; // Assuming fixed format instructions
}
// Update the Location Table
locTable.put(opcode, locCounter);
}
// Close the input file
reader.close();
}
/**
* Pass 2 of the assembler: Generate Object Code.
*
* @param inputFileName Input file containing SIC/XE assembly code.
* @param outputFileName Output file to write the generated object code.
* @throws IOException If an I/O error occurs while reading the input file or writing the output file.
*/
private void pass2(String inputFileName, String outputFileName) throws IOException {
// Define the OPTAB entries for SIC/XE instructions
optab.put("LDX", 0x04);
optab.put("LDA", 0x00);
optab.put("ADD", 0x18);
optab.put("STA", 0x0C);
optab.put("RSUB", 0x4C);
optab.put("TIX", 0x2C);
optab.put("JLT", 0x38);
optab.put("LDS", 0x6C);
optab.put("LDT", 0x74);
optab.put("ADDR", 0x90);
optab.put("COMPR", 0xA0);
optab.put("JSUB", 0x48);
optab.put("CLEAR", 0xB4);
optab.put("TIXR", 0xB8);
optab.put("JEQ", 0x30);
optab.put("J", 0x3C);
// Open the input file for reading and the output file for writing
BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName));
String line;
// Flags to track control sections and program blocks
boolean inControlSection = false;
String currentControlSection = "";
boolean inProgramBlock = false;
String currentProgramBlock = "";
// Process each line to generate object code
while ((line = reader.readLine()) != null) {
String[] tokens = line.split("\\s+");
if (tokens.length < 2) continue;
String label = tokens[0];
String opcode = tokens[1];
// Generate Object Code for instructions
if (optab.containsKey(opcode)) {
Integer operandValue = symTable.get(tokens[2]); // Assuming operand is a symbol
if (operandValue != null) {
// Check if the instruction is format 4 (indicated by a preceding '+')
boolean isFormat4 = opcode.startsWith("+");
// Remove the '+' if present for opcode lookup in OPTAB
String lookupOpcode = isFormat4 ? opcode.substring(1) : opcode;
// Get the opcode value from OPTAB
int opcodeValue = optab.get(lookupOpcode);
// Calculate displacement (disp) for instructions without '+'
int disp = 0;
if (!isFormat4) {
disp = operandValue - locCounter;
}
// Set the format flag (e bit)
int formatFlag = isFormat4 ? 1 : 0;
// Combine opcode, nixbpe bits, and displacement into the object code
int objectCode = (opcodeValue << 24) | (formatFlag << 23) | (disp & 0x7FFFFF);
// Write the generated object code to the output file
writer.write(String.format("%08X", objectCode) + "\n");
} else {
// Handle case where operand value is not found in the symbol table
}
}
}
// Close the input and output files
reader.close();
writer.close();
}
/**
* Display Symbol and Location Tables along with the Object Program for each input file.
*
* @param inputFileName Input file for which tables and object program are displayed.
*/
private void displayTables(String inputFileName) {
// Display tables for the input file
System.out.println("Tables for Input File: " + inputFileName);
System.out.println("==============================================");
// Display Symbol Table
System.out.println("Symbol Table:");
System.out.println("------------------------------------------------------------------");
System.out.printf("%-15s %-15s %-25s %-15s%n", "LINE", "LOC", "SOURCE STATEMENT", "OBJECT CODE");
int line = 1;
for (Map.Entry<String, Integer> entry : symTable.entrySet()) {
System.out.printf("%-15d %-15d %-25s %-15s%n", line++, entry.getValue(), entry.getKey(), "");
}
// Display Location Table
System.out.println("\nLocation Table:");
System.out.println("------------------------------------------------------------------");
System.out.printf("%-15s %-15s %-25s %-15s%n", "LINE", "LOC", "SOURCE STATEMENT", "OBJECT CODE");
line = 1;
try {
BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
String sourceLine;
while ((sourceLine = reader.readLine()) != null) {
String[] tokens = sourceLine.split("\\s+");
if (tokens.length < 2) continue;
String opcode = tokens[1];
// Display Object Code for instructions
if (optab.containsKey(opcode)) {
Integer operandValue = symTable.get(tokens[2]); // Assuming operand is a symbol
if (operandValue != null) {
int objectCode = optab.get(opcode) << 16 | operandValue.intValue();
System.out.printf("%-15d %-15d %-25s %-15s%n", line++, locTable.get(opcode), sourceLine, String.format("%06X", objectCode));
}
}
}
// Close the reader for the input file
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
// Display program length
System.out.println("\nProgram Length: " + programLength);
System.out.println("==============================================\n");
}
}