Advertisement
Bewin

sicTwoPassAssembler

Oct 1st, 2024
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 15.60 KB | None | 0 0
  1. import javax.swing.*;
  2. import java.io.IOException;
  3. import java.io.*;
  4. import java.util.HashMap;
  5. import java.util.LinkedHashMap;
  6. import java.util.Map;
  7. import java.awt.*;
  8. import java.io.File;
  9. import java.io.InputStream;
  10.  
  11. class TwoPassAssemblerGUI extends JFrame {
  12.     private final JTextField inputFileField;
  13.     private final JTextField optabFileField;
  14.     private final JButton assembleBtn;
  15.     private final JTextArea intermediateFileOutput;
  16.     private final JTextArea symbolTableOutput;
  17.     private final JTextArea objectCodeOutput;
  18.  
  19.     public TwoPassAssemblerGUI() throws IOException {
  20.         setTitle("Two-Pass Assembler");
  21.         setSize(800, 650);
  22.         setResizable(false);
  23.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  24.  
  25.         Font font = new Font("Arial", Font.PLAIN, 16);
  26.         Font font2 = new Font("Monospaced", Font.PLAIN, 14);
  27.  
  28.         // Input label and field
  29.         JLabel inputFileLabel = new JLabel("Input File:");
  30.         inputFileLabel.setFont(font);
  31.         inputFileField = new JTextField(30);
  32.         inputFileField.setFont(font);
  33.         JButton browseBtn = new JButton("Browse");
  34.         browseBtn.setFont(font);
  35.         browseBtn.addActionListener(e -> browseFile(inputFileField));
  36.  
  37.         // Input panel
  38.         JPanel inputPanel = new JPanel(new BorderLayout(10, 0));
  39.         inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
  40.         inputPanel.add(inputFileLabel, BorderLayout.WEST);
  41.         inputPanel.add(inputFileField, BorderLayout.CENTER);
  42.         inputPanel.add(browseBtn, BorderLayout.EAST);
  43.  
  44.         // Optab label and field
  45.         JLabel optabFileLabel = new JLabel("Optab File:");
  46.         optabFileLabel.setFont(font);
  47.         optabFileField = new JTextField(30);
  48.         optabFileField.setFont(font);
  49.         JButton optabBrowseBtn = new JButton("Browse");
  50.         optabBrowseBtn.setFont(font);
  51.         optabBrowseBtn.addActionListener(e -> browseFile(optabFileField));
  52.  
  53.         // Optab panel
  54.         JPanel optabPanel = new JPanel(new BorderLayout(10, 0));
  55.         optabPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
  56.         optabPanel.add(optabFileLabel, BorderLayout.WEST);
  57.         optabPanel.add(optabFileField, BorderLayout.CENTER);
  58.         optabPanel.add(optabBrowseBtn, BorderLayout.EAST);
  59.  
  60.         // Assemble button
  61.         assembleBtn = new JButton("Assemble");
  62.         assembleBtn.setFont(new Font("Arial", Font.BOLD, 16));
  63.         assembleBtn.setBackground(new Color(0, 153, 255));
  64.         assembleBtn.setForeground(Color.WHITE);
  65.         assembleBtn.setFocusPainted(false);
  66.         assembleBtn.setPreferredSize(new Dimension(120, 35));
  67.         assembleBtn.addActionListener(e -> runAssembler());
  68.  
  69.         // Button panel
  70.         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
  71.         buttonPanel.add(assembleBtn);
  72.  
  73.         // Text areas
  74.         intermediateFileOutput = new JTextArea(10, 30);
  75.         intermediateFileOutput.setBorder(BorderFactory.createTitledBorder("Intermediate File Output"));
  76.         intermediateFileOutput.setFont(font2);
  77.         intermediateFileOutput.setEditable(false);
  78.  
  79.         symbolTableOutput = new JTextArea(10, 30);
  80.         symbolTableOutput.setBorder(BorderFactory.createTitledBorder("Symbol Table Output"));
  81.         symbolTableOutput.setFont(font2);
  82.         symbolTableOutput.setEditable(false);
  83.  
  84.         objectCodeOutput = new JTextArea(8, 91);
  85.         objectCodeOutput.setBorder(BorderFactory.createTitledBorder("Object Code Output"));
  86.         objectCodeOutput.setFont(font2);
  87.         objectCodeOutput.setEditable(false);
  88.  
  89.         // Panel for text areas
  90.         JPanel textAreaPanel = new JPanel(new GridLayout(1, 2, 10, 10));
  91.         textAreaPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
  92.         textAreaPanel.add(new JScrollPane(intermediateFileOutput));
  93.         textAreaPanel.add(new JScrollPane(symbolTableOutput));
  94.  
  95.         // Bottom panel for object code
  96.         JPanel bottomTextAreaPanel = new JPanel(new BorderLayout());
  97.         bottomTextAreaPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
  98.         bottomTextAreaPanel.add(new JScrollPane(objectCodeOutput), BorderLayout.CENTER);
  99.  
  100.         // Main panel to hold all components
  101.         JPanel mainPanel = new JPanel();
  102.         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
  103.         mainPanel.add(inputPanel);
  104.         mainPanel.add(optabPanel);
  105.         mainPanel.add(buttonPanel);
  106.         mainPanel.add(textAreaPanel);
  107.         mainPanel.add(bottomTextAreaPanel);
  108.  
  109.         add(mainPanel, BorderLayout.CENTER);
  110.  
  111.         // Center the window on screen
  112.         setLocationRelativeTo(null);
  113.     }
  114.  
  115.     //Browse file
  116.     private void browseFile(JTextField field) {
  117.         JFileChooser fileChooser = new JFileChooser();
  118.         int option = fileChooser.showOpenDialog(this);
  119.         if (option == JFileChooser.APPROVE_OPTION) {
  120.             File file = fileChooser.getSelectedFile();
  121.             field.setText(file.getPath());
  122.         }
  123.     }
  124.  
  125.     // Run the assembler when the "Assemble" button is clicked
  126.     private void runAssembler() {
  127.         String inputFile = inputFileField.getText();
  128.         String optabFile = optabFileField.getText();
  129.  
  130.         if (inputFile.isEmpty()) {
  131.             JOptionPane.showMessageDialog(this, "Please provide the input file!", "Error", JOptionPane.ERROR_MESSAGE);
  132.             return;
  133.         }
  134.  
  135.         // Disable the Assemble button to prevent multiple clicks
  136.         assembleBtn.setEnabled(false);
  137.  
  138.         // Use a SwingWorker to handle the assembly process in the background
  139.         SwingWorker<Void, Void> worker = new SwingWorker<>() {
  140.             @Override
  141.             protected Void doInBackground() {
  142.                 TwoPassAssembler assembler = new TwoPassAssembler(inputFile, optabFile);
  143.                 try {
  144.                     assembler.loadOptab();   // Load opcode table
  145.                     assembler.passOne();     // Run first pass
  146.                     assembler.passTwo();     // Run second pass
  147.  
  148.                     // Display outputs from the HashMaps instead of files
  149.                     displayIntermediateCode(assembler.getIntermediate(), assembler.getIntermediateStart());
  150.                     displaySymbolTable(assembler.getSymtab());
  151.                     displayObjectCode(assembler.getObjectCode());
  152.  
  153.                 } catch (IOException e) {
  154.                     JOptionPane.showMessageDialog(TwoPassAssemblerGUI.this, "Error running the assembler: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
  155.                 }
  156.                 return null;
  157.             }
  158.  
  159.             @Override
  160.             protected void done() {
  161.                 // Re-enable the Assemble button once processing is complete
  162.                 assembleBtn.setEnabled(true);
  163.             }
  164.         };
  165.  
  166.         worker.execute();
  167.     }
  168.  
  169.  
  170.     // Method to display intermediate code from the HashMap
  171.     private void displayIntermediateCode(Map<Integer, String> intermediate, Map<Integer, String> intermediateStart) {
  172.         StringBuilder content = new StringBuilder();
  173.         for (Map.Entry<Integer, String> entry : intermediateStart.entrySet()) {
  174.             content.append(String.format("%04X",entry.getKey())).append(entry.getValue()).append("\n");
  175.         }
  176.         for (Map.Entry<Integer, String> entry : intermediate.entrySet()) {
  177.             content.append(String.format("%04X",entry.getKey())).append(entry.getValue()).append("\n");
  178.         }
  179.         intermediateFileOutput.setText(content.toString());  // Display in the text area
  180.     }
  181.  
  182.     // Method to display symbol table from the HashMap
  183.     private void displaySymbolTable(Map<String, Integer> symtab) {
  184.         StringBuilder content = new StringBuilder();
  185.         for (Map.Entry<String, Integer> entry : symtab.entrySet()) {
  186.             content.append(entry.getKey()).append("\t").append(String.format("%04X",entry.getValue())).append("\n");
  187.         }
  188.         symbolTableOutput.setText(content.toString());  // Display in the text area
  189.     }
  190.  
  191.     // Method to display object code from the HashMap
  192.     private void displayObjectCode(Map<Integer, String> objectCode) {
  193.         StringBuilder content = new StringBuilder();
  194.         for (Map.Entry<Integer, String> entry : objectCode.entrySet()) {
  195.             content.append(entry.getValue()).append("\n");
  196.         }
  197.         objectCodeOutput.setText(content.toString());  // Display in the text area
  198.     }
  199.  
  200.     public Icon getBrowseIcon() throws IOException {
  201.         // Use ClassLoader to get the resource as an InputStream
  202.         InputStream inputStream = getClass().getClassLoader().getResourceAsStream("browse-icon.png");
  203.         if (inputStream == null) {
  204.             System.out.println("Resource not found: browse-icon.png");
  205.             return null;
  206.         }
  207.  
  208.         // Create an ImageIcon from the InputStream
  209.         return new ImageIcon(inputStream.readAllBytes());
  210.     }
  211. }
  212.  
  213. class TwoPassAssembler {
  214.     private final String inputFile;
  215.     private final String optabFile;
  216.     private final Map<String, String> optab = new HashMap<>();
  217.     private final Map<String, Integer> symtab = new LinkedHashMap<>();
  218.     private final Map<Integer, String> intermediate = new LinkedHashMap<>();
  219.     private final Map<Integer, String> intermediateStart = new LinkedHashMap<>();
  220.     private final Map<Integer, String> objectCode = new LinkedHashMap<>();
  221.     private int locctr = 0;
  222.     private int start = 0;
  223.     private int length = 0;
  224.  
  225.     public TwoPassAssembler(String inputFile, String optabFile) {
  226.         this.inputFile = inputFile;
  227.         this.optabFile = optabFile;
  228.     }
  229.  
  230.     public void loadOptab() throws IOException {
  231.         BufferedReader reader = new BufferedReader(new FileReader(optabFile));
  232.         String line;
  233.         while ((line = reader.readLine()) != null) {
  234.             String[] parts = line.split("\\s+");
  235.             optab.put(parts[0], parts[1]);
  236.         }
  237.         reader.close();
  238.     }
  239.  
  240.     public void passOne() throws IOException {
  241.         BufferedReader reader = new BufferedReader(new FileReader(inputFile));
  242.         String line = reader.readLine();
  243.         String[] parts = line.split("\\s+");
  244.  
  245.         if (parts[1].equals("START")) {
  246.             start = Integer.parseInt(parts[2], 16); // Parse start as hexadecimal
  247.             locctr = start;
  248.             intermediateStart.put(locctr, String.format("\t%s\t%s\t%s", parts[0], parts[1], parts[2]));
  249.             line = reader.readLine();
  250.         } else {
  251.             locctr = 0;
  252.         }
  253.  
  254.         // Process each line
  255.         while (line != null) {
  256.             parts = line.split("\\s+");
  257.             if (parts[1].equals("END")) break;
  258.  
  259.             // Store intermediate with location counter in hex format
  260.             intermediate.put(locctr, String.format("\t%s\t%s\t%s", parts[0], parts[1], parts[2]));
  261.  
  262.             // Insert into symbol table if label exists
  263.             if (!parts[0].equals("-")) {
  264.                 symtab.put(parts[0], locctr);
  265.             }
  266.  
  267.             // Update locctr based on the opcode
  268.             if (optab.containsKey(parts[1])) {
  269.                 locctr += 3;
  270.             } else if (parts[1].equals("WORD")) {
  271.                 locctr += 3;
  272.             } else if (parts[1].equals("BYTE")) {
  273.                 locctr += parts[2].length() - 3;
  274.             } else if (parts[1].equals("RESW")) {
  275.                 locctr += 3 * Integer.parseInt(parts[2]);
  276.             } else if (parts[1].equals("RESB")) {
  277.                 locctr += Integer.parseInt(parts[2]);
  278.             }
  279.  
  280.             line = reader.readLine();
  281.         }
  282.  
  283.         // Store final line in intermediate and calculate program length
  284.         intermediate.put(locctr, String.format("\t%s\t%s\t%s", parts[0], parts[1], parts[2]));
  285.         length = locctr - start;
  286.  
  287.         reader.close();
  288.     }
  289.  
  290.     public void passTwo() throws IOException {
  291.         String line;
  292.         String[] parts;
  293.  
  294.         String startLine = intermediateStart.get(start);
  295.         String[] startParts = startLine.trim().split("\\s+");
  296.  
  297.         // Handle "START" directive
  298.         if (startParts[1].equals("START")) {
  299.             objectCode.put(0, "H^ " + startParts[0] + "^ " + String.format("%06X", start) + "^ " + String.format("%06X", length));
  300.             //line = intermediate.get(start + 1);
  301.         } else {
  302.             objectCode.put(0, "H^ " + " " + "^ 0000^ " + String.format("%06X", length));
  303.         }
  304.  
  305.         StringBuilder textRecord = new StringBuilder();
  306.         int textStartAddr = 0;
  307.         int textLength = 0;
  308.  
  309.         for (int loc : intermediate.keySet()) {
  310.  
  311.             line = intermediate.get(loc);
  312.             parts = line.trim().split("\\s+");
  313.             if (parts.length < 3) continue;
  314.  
  315.             if (parts[2].equals("END")) break;
  316.  
  317.             if (textLength == 0) {
  318.                 textStartAddr = loc;
  319.                 textRecord.append("T^ ").append(String.format("%06X", textStartAddr)).append("^ ");
  320.             }
  321.  
  322.             // Generate object code for each line
  323.             if (optab.containsKey(parts[1])) {
  324.                 String machineCode = optab.get(parts[1]);
  325.                 int address = symtab.getOrDefault(parts[2], 0);
  326.                 String code = machineCode + String.format("%04X", address);
  327.                 textRecord.append(code).append("^ ");
  328.                 textLength += code.length() / 2;
  329.             } else if (parts[1].equals("WORD")) {
  330.                 String wordCode = String.format("%06X", Integer.parseInt(parts[2]));
  331.                 textRecord.append(wordCode).append("^ ");
  332.                 textLength += wordCode.length() / 2;
  333.             } else if (parts[1].equals("BYTE")) {
  334.                 String byteCode = parts[2].substring(2, parts[2].length() - 1); // Extract value from BYTE literal
  335.                 textRecord.append(byteCode).append("^ ");
  336.                 textLength += byteCode.length() / 2;
  337.             } else if (parts[1].equals("RESW") || parts[1].equals("RESB")) {
  338.                 // If we hit RESW/RESB, flush the current text record and start a new one after reserving memory
  339.                 if (textLength > 0) {
  340.                     objectCode.put(textStartAddr, textRecord.toString());
  341.                     textRecord = new StringBuilder();
  342.                     textLength = 0;
  343.                 }
  344.                 continue; // Do not generate object code for reserved space
  345.             }
  346.  
  347.             if (textLength >= 30) { // Text records should not exceed 30 bytes (60 hex characters)
  348.                 objectCode.put(textStartAddr, textRecord.toString());
  349.                 textRecord = new StringBuilder();
  350.                 textLength = 0;
  351.             }
  352.         }
  353.  
  354.         // Write remaining text record if not empty
  355.         if (textLength > 0) {
  356.             objectCode.put(textStartAddr, textRecord.toString());
  357.         }
  358.  
  359.         // Write End record
  360.         objectCode.put(locctr, "E^ " + String.format("%06X", start));
  361.     }
  362.  
  363.  
  364.     public Map<Integer, String> getIntermediate() {
  365.         return intermediate;
  366.     }
  367.  
  368.     public Map<Integer, String> getIntermediateStart() {
  369.         return intermediateStart;
  370.     }
  371.  
  372.     public Map<String, Integer> getSymtab() {
  373.         return symtab;
  374.     }
  375.  
  376.     public Map<Integer, String> getObjectCode() {
  377.         return objectCode;
  378.     }
  379.  
  380. }
  381.  
  382. public class Main {
  383.     public static void main(String[] args) {
  384.         SwingUtilities.invokeLater(() -> {
  385.             TwoPassAssemblerGUI gui;
  386.             try {
  387.                 gui = new TwoPassAssemblerGUI();
  388.             } catch (IOException e) {
  389.                 throw new RuntimeException(e);
  390.             }
  391.             gui.setVisible(true);
  392.         });
  393.     }
  394. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement