├── .gitignore ├── src └── main │ └── java │ └── me │ └── bodiw │ ├── gui │ ├── ControlReg.java │ ├── Colors.java │ ├── ControlRegLabel.java │ ├── WordLabel.java │ ├── AsciiLabel.java │ └── Gui.java │ ├── model │ ├── Registers.java │ └── Word.java │ ├── process │ ├── CompilerProcess.java │ └── AssemblerProcess.java │ ├── Config.java │ ├── Names.java │ ├── interpreter │ └── Interpreter.java │ └── App.java ├── configEjemploWindows.json ├── config.json ├── ejemplo.ens ├── pom.xml ├── README.md └── ComoProgramarEnsamblador.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | target/ 3 | .idea/ 4 | bin/ 5 | 6 | traza.log 7 | config.json 8 | estortura.bin 9 | dependency-reduced-pom.xml -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/ControlReg.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | public class ControlReg { 4 | 5 | public int value; 6 | 7 | public int lastCycleUpdate; 8 | 9 | public ControlReg() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/model/Registers.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.model; 2 | 3 | public class Registers { 4 | 5 | public Word[] regs; 6 | 7 | public Registers() { 8 | regs = new Word[32]; 9 | for (int i = 0; i < regs.length; i++) { 10 | regs[i] = new Word(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /configEjemploWindows.json: -------------------------------------------------------------------------------- 1 | { 2 | "EMULADOR": "emu\\88110.exe", 3 | "COMPILADOR": "emu\\88110e.exe", 4 | "CONF": "emu\\serie", 5 | "CODIGO": "cvd.ens", 6 | "SCALE": "1.1", 7 | "STEP_INICIO": "1", 8 | "SKIP_INICIO": "0", 9 | "MEM_ADDR_INICIO": "4000", 10 | "BITMAP_TYPE": "MEMORY", 11 | "BITMAP_ADDR": "4000", 12 | "TAG_INICIO": "PPAL", 13 | "TAG_BREAKPOINT": "" 14 | } 15 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "EMULADOR": "/path/to/emu/em88110", 3 | "COMPILADOR": "/path/to/emu/88110e", 4 | "CONF": "/path/to/src/serie", 5 | "CODIGO": "/path/to/src/pro.ens", 6 | "SCALE": "1.1", 7 | "STEP_INICIO": "1", 8 | "SKIP_INICIO": "0", 9 | "MEM_ADDR_INICIO": "4000", 10 | "BITMAP_TYPE": "MEMORY", 11 | "BITMAP_ADDR": "4000", 12 | "TAG_INICIO": "START", 13 | "TAG_BREAKPOINT": "" 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/Colors.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | import java.awt.Color; 4 | 5 | import javax.swing.BorderFactory; 6 | import javax.swing.border.Border; 7 | 8 | public class Colors { 9 | public static final Color UPDATED = new Color(104, 88, 22); 10 | public static final Color MODIFIED = new Color(51, 51, 51); 11 | public static final Color UNUPDATED = new Color(51, 51, 51); 12 | public static final Color BACKGROUND = new Color(30, 30, 30); 13 | public static final Color FOREGROUND = new Color(205, 205, 205); 14 | 15 | public static final Border BORDER = BorderFactory.createLineBorder(new Color(65, 65, 65)); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/ControlRegLabel.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | import javax.swing.JLabel; 4 | 5 | public class ControlRegLabel extends JLabel { 6 | 7 | public ControlReg reg; 8 | 9 | public ControlRegLabel(ControlReg reg) { 10 | this.reg = reg; 11 | this.setOpaque(true); 12 | } 13 | 14 | public String toString() { 15 | return "" + reg.value; 16 | } 17 | 18 | public void update(int cycle) { 19 | if (cycle <= reg.lastCycleUpdate) { 20 | this.setText(this.toString()); 21 | this.setBackground(Colors.UPDATED); 22 | reg.lastCycleUpdate = cycle; 23 | } else if (reg.lastCycleUpdate != 0 24 | && this.getBackground() == Colors.UPDATED) { 25 | this.setBackground(Colors.UNUPDATED); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ejemplo.ens: -------------------------------------------------------------------------------- 1 | LEA: MACRO (reg, ETIQ) 2 | or reg, r0, low(ETIQ) 3 | or.u reg, reg, high(ETIQ) 4 | ENDMACRO 5 | 6 | DBNZ: MACRO (reg, ETIQ) 7 | sub reg, reg, 1 8 | cmp r2, reg, r0 9 | bb0 eq, r2, ETIQ 10 | ENDMACRO 11 | 12 | LOAD: MACRO (reg, ETIQ) 13 | LEA (reg, ETIQ) 14 | ld reg, reg, r0 15 | ENDMACRO 16 | 17 | PUSH: MACRO (reg) 18 | subu r30, r30, 4 19 | st reg, r30, r0 20 | ENDMACRO 21 | 22 | POP: MACRO (reg) 23 | ld reg, r30, r0 24 | addu r30, r30, 4 25 | ENDMACRO 26 | 27 | org 4000 28 | cadena: data "\H\O\L\AHola buenos dias" 29 | 30 | START: 31 | LEA (r10, cadena) 32 | ld.bu r2, r10, r0 33 | st r2, r0, r10 34 | 35 | END: stop -------------------------------------------------------------------------------- /src/main/java/me/bodiw/model/Word.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.model; 2 | 3 | public class Word { 4 | 5 | public byte[] data; 6 | 7 | public int lastCycleUpdate; 8 | 9 | public Word() { 10 | data = new byte[4]; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return String.format("%02X %02X %02X %02X", data[0], data[1], data[2], data[3]); 16 | } 17 | 18 | public String toIntString() { 19 | int value = 0; 20 | for (int i = 0; i < 4; i++) { 21 | value += (data[i] & 0xFF) << (8 * i); 22 | } 23 | return String.format("%d", value); 24 | } 25 | 26 | public boolean equals(byte[] data2) { 27 | for (int i = 0; i < 4; i++) { 28 | if (data[i] != data2[i]) { 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/process/CompilerProcess.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.process; 2 | 3 | import java.io.IOException; 4 | 5 | public class CompilerProcess { 6 | 7 | public String compiler, code, start, output; 8 | 9 | public CompilerProcess(String compiler, String code, String start, String output) { 10 | this.compiler = compiler; 11 | this.code = code; 12 | this.start = start; 13 | this.output = output; 14 | } 15 | 16 | public void compile() throws IOException, InterruptedException { 17 | ProcessBuilder pb = new ProcessBuilder(compiler, "-e", start, "-o", output, code); 18 | pb.redirectErrorStream(true); 19 | Process p = pb.start(); 20 | p.waitFor(); 21 | 22 | String output = new String(p.getInputStream().readAllBytes()); 23 | 24 | if (output.contains("88110.ens-ERROR")) { 25 | throw new RuntimeException(output); 26 | } else if (output.contains("No pude abrir")) { 27 | throw new RuntimeException(output + code); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/WordLabel.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | import javax.swing.JLabel; 4 | 5 | import me.bodiw.model.Word; 6 | 7 | public class WordLabel extends JLabel { 8 | 9 | public enum DisplayMode { 10 | HEX, DEC 11 | } 12 | 13 | public Word word; 14 | private DisplayMode displayMode = DisplayMode.HEX; 15 | 16 | public WordLabel(Word word) { 17 | this.word = word; 18 | this.createToolTip(); 19 | this.setOpaque(true); 20 | } 21 | 22 | public void setWord(Word word) { 23 | this.word = word; 24 | } 25 | 26 | public void update(int cycle) { 27 | if (cycle <= word.lastCycleUpdate) { 28 | this.setText(this.getDisplayText()); 29 | this.setBackground(Colors.UPDATED); 30 | word.lastCycleUpdate = cycle; 31 | } else if (word.lastCycleUpdate != 0 32 | && this.getBackground() == Colors.UPDATED) { 33 | this.setBackground(Colors.UNUPDATED); 34 | } 35 | } 36 | 37 | public String getDisplayText() { 38 | if (displayMode == DisplayMode.HEX) { 39 | return word.toString(); 40 | } else { 41 | return word.toIntString(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/AsciiLabel.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | import javax.swing.JLabel; 4 | 5 | import me.bodiw.model.Word; 6 | 7 | public class AsciiLabel extends JLabel { 8 | 9 | public Word word; 10 | 11 | public AsciiLabel(Word word) { 12 | this.word = word; 13 | this.setOpaque(true); 14 | } 15 | 16 | public void setWord(Word word) { 17 | this.word = word; 18 | } 19 | 20 | public void update(int cycle) { 21 | if (cycle <= word.lastCycleUpdate) { 22 | this.setText(this.toString()); 23 | this.setBackground(Colors.UPDATED); 24 | word.lastCycleUpdate = cycle; 25 | } else if (word.lastCycleUpdate != 0 26 | && this.getBackground() == Colors.UPDATED) { 27 | this.setBackground(Colors.UNUPDATED); 28 | } 29 | } 30 | 31 | public String toString() { 32 | StringBuilder s = new StringBuilder(4); 33 | for (int i = 0; i < 4; i++) { 34 | if (word.data[i] >= 32 && word.data[i] <= 126) { 35 | s.append((char) word.data[i]); 36 | } else if (word.data[i] == 0) 37 | s.append('.'); 38 | else { 39 | s.append((char) -1); 40 | } 41 | } 42 | return s.toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/Config.java: -------------------------------------------------------------------------------- 1 | package me.bodiw; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | import java.lang.reflect.Type; 7 | import java.util.HashMap; 8 | 9 | import com.google.gson.Gson; 10 | import com.google.gson.reflect.TypeToken; 11 | 12 | public class Config { 13 | 14 | String configPath; 15 | public String emulator, compiler, config, code, start, bin, bitmapType, breakpoint; 16 | public int iniMem, iniStep = 1, iniSkip, iniBitmap; 17 | public float scale; 18 | 19 | public Config(String configPath) { 20 | this.configPath = configPath; 21 | } 22 | 23 | public void load() throws IOException { 24 | Gson gson = new Gson(); 25 | BufferedReader bufferedReader = new BufferedReader(new FileReader(configPath)); 26 | 27 | Type type = new TypeToken>() { 28 | }.getType(); 29 | HashMap json = gson.fromJson(bufferedReader, type); 30 | bufferedReader.close(); 31 | 32 | emulator = json.get("EMULADOR"); 33 | compiler = json.get("COMPILADOR"); 34 | config = json.get("CONF"); 35 | code = json.get("CODIGO"); 36 | breakpoint = json.get("TAG_BREAKPOINT"); 37 | start = json.get("TAG_INICIO"); 38 | 39 | iniMem = Integer.parseInt(json.get("MEM_ADDR_INICIO")); 40 | iniStep = Integer.parseInt(json.get("STEP_INICIO")); 41 | iniSkip = Integer.parseInt(json.get("SKIP_INICIO")); 42 | iniBitmap = Integer.parseInt(json.get("BITMAP_ADDR")); 43 | bitmapType = json.get("BITMAP_TYPE"); 44 | 45 | scale = Float.parseFloat(json.get("SCALE")); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/Names.java: -------------------------------------------------------------------------------- 1 | package me.bodiw; 2 | 3 | public class Names { 4 | 5 | public static final String[] NAMES = { 6 | "En Ensamblador, tus programas duran tan poco como tu en la cama", 7 | "Espero que te paguen por horas si programas ensamblador", 8 | "MC88K, powered by your tears", 9 | "public static void main(String[] args){", 10 | "\"OR 1=1;--", 11 | "ESTRUCTURA VA A TERMINAR CON MI CORDURA", 12 | "La vida es dura, pero mas dura es Estructura", 13 | "Replanteate las decisiones que te han llevado hasta aqui", 14 | "2 de cada 4 personas son la mitad", 15 | "Patata", 16 | "No se que poner aqui", 17 | "It's dangerous to debug assembly alone, take this gui", 18 | "Cagaste", 19 | "Cuanto es 5 + 8?", 20 | "https://yt.be/tcJ3V", 21 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 22 | "Preferiria estar jugando a Maincraft", 23 | "Buena tula bro", 24 | "Llevas dos meses en coma, despierta por favor", 25 | "We have contacted you to talk about your car's extended warranty", 26 | "Sacaras un 10 en Estructura... En binario", 27 | "sudo rm -rf /", 28 | "$ touch grass.txt", 29 | "I dont want a lot for Christmas, there is just one thing I need", 30 | "\"Los numeros no dan miedo\", el % de aprobados de estru : ", 31 | "https://www.youtube.com/watch?v=QH2-TGUlwu4", 32 | "", 33 | "Por la tercera matricula vamos ya joer...", 34 | "Fundamentos Cloud es absolutamente la mejor asignatura de la carrera", 35 | "Estoy en tus paredes", 36 | "Algun dia optimizare esto para que no esten todos estos titulos en tu RAM", 37 | "Losing-your-sanity-any%-speedrun.ens", 38 | "POR FAVOR LLAMEN A LA POLICIA ME ESTAN MATANDO", 39 | "Let him cook", 40 | "Jesse we need to code", 41 | "GUI Ensamblador 100% real no fake 1 link mega 4k full hd no virus" 42 | }; 43 | } -------------------------------------------------------------------------------- /src/main/java/me/bodiw/interpreter/Interpreter.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.interpreter; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class Interpreter { 9 | private static final Pattern PC_PATTERN = Pattern.compile("PC=(\\d+)"); 10 | private static final Pattern INSTRUCTION_PATTERN = Pattern.compile("PC=\\d+\\s+(.*?)\\s+Tot\\. Inst"); 11 | private static final Pattern TOTAL_INSTRUCTIONS_PATTERN = Pattern.compile("Inst: (\\d+)"); 12 | private static final Pattern CYCLE_PATTERN = Pattern.compile("Ciclo : (\\d+)"); 13 | private static final Pattern FLAG_PATTERN = Pattern.compile("FL=(\\d) FE=(\\d) FC=(\\d) FV=(\\d) FR=(\\d)"); 14 | private static final Pattern REGISTER_PATTERN = Pattern.compile("R(\\d{2}) = ([0-9A-F]{8}) h"); 15 | private static final Pattern MEMORY_PATTERN = Pattern 16 | .compile("(\\d+)\\s+([0-9A-F]{8})\\s+([0-9A-F]{8})\\s+([0-9A-F]{8})\\s+([0-9A-F]{8})"); 17 | 18 | public static Map readRegs(String input) { 19 | Map values = new HashMap<>(); 20 | Matcher m; 21 | 22 | m = PC_PATTERN.matcher(input); 23 | if (m.find()) { 24 | values.put("PC", Integer.parseInt(m.group(1))); 25 | } 26 | 27 | m = INSTRUCTION_PATTERN.matcher(input); 28 | if (m.find()) { 29 | values.put("Instruction", m.group(1).trim().replaceAll("\\s+", " ")); 30 | } 31 | 32 | m = TOTAL_INSTRUCTIONS_PATTERN.matcher(input); 33 | if (m.find()) { 34 | values.put("TotalInstructions", Integer.parseInt(m.group(1))); 35 | } 36 | 37 | m = CYCLE_PATTERN.matcher(input); 38 | if (m.find()) { 39 | values.put("Cycle", Integer.parseInt(m.group(1))); 40 | } 41 | 42 | m = FLAG_PATTERN.matcher(input); 43 | if (m.find()) { 44 | values.put("FL", Integer.parseInt(m.group(1))); 45 | values.put("FE", Integer.parseInt(m.group(2))); 46 | values.put("FC", Integer.parseInt(m.group(3))); 47 | values.put("FV", Integer.parseInt(m.group(4))); 48 | values.put("FR", Integer.parseInt(m.group(5))); 49 | } 50 | 51 | m = REGISTER_PATTERN.matcher(input); 52 | 53 | values.put("R00", new byte[] { 0, 0, 0, 0 }); 54 | while (m.find()) { 55 | String reg = "R" + m.group(1); 56 | byte[] bytes = new byte[4]; 57 | for (int i = 0; i < 4; i++) { 58 | int value = Integer.parseInt(m.group(2).substring(i * 2, (i + 1) * 2), 16); 59 | bytes[i] = (byte) value; 60 | } 61 | values.put(reg, bytes); 62 | } 63 | 64 | return values; 65 | } 66 | 67 | public static Map readMem(String input) { 68 | Map memoryValues = new HashMap<>(); 69 | Matcher m = MEMORY_PATTERN.matcher(input); 70 | 71 | while (m.find()) { 72 | int identifier = Integer.parseInt(m.group(1)); 73 | byte[][] bytesArray = new byte[4][4]; 74 | 75 | for (int i = 0; i < 4; i++) { 76 | for (int j = 0; j < 4; j++) { 77 | int value = Integer.parseInt(m.group(i + 2).substring(j * 2, (j + 1) * 2), 16); 78 | bytesArray[i][j] = (byte) value; 79 | } 80 | } 81 | memoryValues.put(identifier, bytesArray); 82 | } 83 | return memoryValues; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/App.java: -------------------------------------------------------------------------------- 1 | package me.bodiw; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.swing.JFrame; 6 | import javax.swing.JOptionPane; 7 | import javax.swing.WindowConstants; 8 | 9 | import com.formdev.flatlaf.FlatDarkLaf; 10 | 11 | import me.bodiw.gui.Gui; 12 | import me.bodiw.process.AssemblerProcess; 13 | import me.bodiw.process.CompilerProcess; 14 | 15 | public class App { 16 | 17 | public static String configPath = "config.json"; 18 | 19 | static JFrame errorFrame; 20 | 21 | public static void main(String[] args) { 22 | 23 | if (args.length > 0) { 24 | configPath = args[0]; 25 | } 26 | 27 | loadErrorFrame(); 28 | 29 | FlatDarkLaf.setup(); 30 | 31 | Config cf = loadConfig(configPath); 32 | 33 | if (cf == null) { 34 | errorFrame.dispose(); 35 | return; 36 | } 37 | 38 | AssemblerProcess ap = null; 39 | 40 | ap = createAssemblerProcess(cf); 41 | 42 | if (ap == null) { 43 | errorFrame.dispose(); 44 | return; 45 | } 46 | 47 | String name = Names.NAMES[(int) (Math.random() * Names.NAMES.length)]; 48 | 49 | Gui gui = new Gui(name, ap); 50 | 51 | gui.setLocationRelativeTo(null); 52 | gui.setVisible(true); 53 | gui.requestFocus(); 54 | 55 | } 56 | 57 | public static AssemblerProcess createAssemblerProcess(Config cf) { 58 | AssemblerProcess ap = null; 59 | 60 | try { 61 | ap = new AssemblerProcess(cf); 62 | System.out.println("Assembler process created"); 63 | } catch (IOException e) { 64 | showError("Assembler builder", "No se ha podido crear un proceso Ensamblador\n" 65 | + "Esta mal la direccion del emulador o del archivo conf(serie)?\n" 66 | + e.getMessage()); 67 | e.printStackTrace(); 68 | return null; 69 | } catch (RuntimeException e) { 70 | showError("Assembler builder", e.getMessage()); 71 | e.printStackTrace(); 72 | return null; 73 | } 74 | 75 | return ap; 76 | } 77 | 78 | public static Config loadConfig(String configPath) { 79 | Config config = new Config(configPath); 80 | 81 | // Failed to read file 82 | try { 83 | config.load(); 84 | } catch (IOException e) { 85 | showError("Config", "Failed to read " + configPath + " config file"); 86 | e.printStackTrace(); 87 | return null; 88 | } 89 | 90 | CompilerProcess cp = new CompilerProcess( 91 | config.compiler, 92 | config.code, 93 | config.start, 94 | "estortura.bin"); 95 | 96 | try { 97 | cp.compile(); 98 | } catch (IOException | InterruptedException e) { 99 | showError("Compiler", "No se ha podido compilar el codigo\n" + e.getMessage()); 100 | e.printStackTrace(); 101 | return null; 102 | } catch (RuntimeException e) { 103 | showError("Compiler", e.getMessage()); 104 | e.printStackTrace(); 105 | return null; 106 | } 107 | 108 | config.bin = "estortura.bin"; 109 | return config; 110 | } 111 | 112 | public static void showError(String source, String message) { 113 | JOptionPane.showMessageDialog( 114 | errorFrame, 115 | message, 116 | source, 117 | JOptionPane.ERROR_MESSAGE); 118 | } 119 | 120 | private static void loadErrorFrame() { 121 | errorFrame = new JFrame(); 122 | errorFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 123 | errorFrame.setAlwaysOnTop(true); 124 | } 125 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | me.bodiw 8 | estortura 9 | 0.1.1 10 | 11 | estortura 12 | 13 | http://www.example.com 14 | 15 | 16 | UTF-8 17 | 1.7 18 | 1.7 19 | 20 | 21 | 22 | 23 | com.formdev 24 | flatlaf 25 | 3.2.5 26 | 27 | 28 | com.google.code.gson 29 | gson 30 | 2.10.1 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | maven-clean-plugin 41 | 3.1.0 42 | 43 | 44 | 45 | maven-resources-plugin 46 | 3.0.2 47 | 48 | 49 | maven-compiler-plugin 50 | 3.8.0 51 | 52 | 53 | maven-surefire-plugin 54 | 2.22.1 55 | 56 | 57 | maven-jar-plugin 58 | 3.0.2 59 | 60 | 61 | maven-install-plugin 62 | 2.5.2 63 | 64 | 65 | maven-deploy-plugin 66 | 2.8.2 67 | 68 | 69 | 70 | maven-site-plugin 71 | 3.7.1 72 | 73 | 74 | maven-project-info-reports-plugin 75 | 3.0.0 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-jar-plugin 83 | 3.2.0 84 | 85 | 86 | 87 | true 88 | libs/ 89 | me.bodiw.App 90 | 91 | 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-shade-plugin 97 | 3.2.4 98 | 99 | 100 | package 101 | 102 | shade 103 | 104 | 105 | 106 | 107 | me.bodiw.App 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Estortura 2 | 3 | Estructura va a terminar con mi Cordura 4 | 5 | ![image](https://github.com/Bodiw/Estortura/assets/58666162/01c13382-cbb3-4213-ad85-484debb25356) 6 | 7 | ## Descripcion 8 | 9 | Estortura es una GUI en Java que sirve como "Wrapper" del Emulador MC88110 10 | En otras palabras, envuelve el emulador de ensamblador del MC88110 y le proporciona una interfaz grafica a la salida generada por este. 11 | 12 | ## Funcionalidades 13 | 14 | ### Display de Registros , Registo de control y Memoria Principal 15 | 16 | La GUI representa en tiempo real el valor de los registros y de la Memoria principal uno junto al otro 17 | 18 | ### Highlight de actualizaciones 19 | 20 | Tanto en registros como en Memoria, un cambio en el valor actualiza el color de la celda a uno mas llamativo para avisar de un cambio ocurrido. Si la celda en algun momento fue modificada pero no en la ultima instruccion, se muestra un color mas apagado 21 | 22 | ### Traductor Ascii 23 | 24 | Tanto los registros como la MP disponen de un panel Ascii adyacente que proporciona una traduccion a ASCII instantanea 25 | 26 | ### Reload 27 | 28 | Mi parte favorita. 29 | Un unico boton, que vuelve a compilar y ejecutar el archivo de codigo fuente, permitiendo rapidas actualizaciones de codigo. 30 | 31 | El uso del compilador genera un archivo temporal en el directorio actual `estortura.bin` 32 | 33 | ### Atajos de teclado 34 | 35 | Con la version 0.1.0, ahora se disponen de atajos de teclado para acelerar el debugging de la interfaz 36 | 37 | | Tecla | Descripcion | 38 | | ---------------- | ------------------------ | 39 | | F5 | Reload | 40 | | T | Realiza t steps | 41 | | W | Incrementa steps en 1 | 42 | | S | Decrementa steps en 1 | 43 | | D | Realiza 1 Step | 44 | | Flecha Izquierda | Incrementa memoria en 16 | 45 | | Flecha Derecha | Decrementa memoria en 16 | 46 | | V | Recarga la memoria | 47 | | M | Recarga la memoria | 48 | 49 | ### Bitmap 50 | 51 | Tanto en configuracion inicial como haciendo click sobre una celda de Registros o Memoria o una Ascii, actualiza el Bitmap a seguir dicha celda y mostrar su valor en bits. 52 | 53 | ### Step 54 | 55 | Ejecucion secuencial de 'Steps' Instrucciones al pulsar el boton. Se puede usar la rueda de raton para cambiar su valor 56 | 57 | ### Memoria 58 | 59 | Al igual que Step, la rueda de raton cambia su valor. Memoria muestra la direccion a partir de la cual mostrar la MemoriaPrincipal. Tras cambiar el valor, cualquier actualizacion o pulsr en 'Memoria' actualizara la memoria principal 60 | 61 | ### Stdin/Stdout 62 | 63 | La pestaña de Sdtout junto a Memoria permite ver la salida del emulador como fue diseñado en su principio. 64 | Stdin proporciona enviar comandos a este. 65 | No todas las acciones de la GUI proporcionan feedback a traves de Stdout, pero si todas aquellas mediante Stdin. 66 | 67 | Stdin funciona tanto como pulsando el boton 'Stdin' para enviar el comando como la tecla Enter. La tecla Esc permite desenfocar el campo de texto 68 | 69 | ### Last/Next 70 | 71 | Displays de ultimo comando y de siguiente instruccion del emulador 72 | 73 | ## Configuracion 74 | 75 | El archivo `config.json` en la raiz del repositorio sirve como ejemplo de una configuracion base para la GUI. 76 | Por defecto, la GUI busca un `config.json` en el directorio activo, pero tambien se puede sobreescribir mediante argumentos en la linea de comandos, llamandolo como `java -jar estortura.jar miConfiguracion.json`, teniendo java instalado (Esta version ha sido construida con Java 17) 77 | 78 | Los campos del `config.json` son siguientes: 79 | | Campo | Descripcion | 80 | | --- | --- | 81 | | EMULADOR| Direccion del archivo ejecutable del emulador | 82 | | COMPILADOR| Direccion del archivo ejecutable del compilador | 83 | | CONF| Direccion del archivo de configuracion del emulador | 84 | | CODIGO| Codigo fuente de Ensamblador, el famoso 'CVD.ens' | 85 | | SCALE| Escala de la GUI, por defecto es 1.1 | 86 | | STEP_INICIO| Valor inicial del boton de Step | 87 | | SKIP_INICIO| Cuantas instrucciones ejecutar al incio del programa| 88 | | MEM_ADDR_INICIO| Direccion de Memoria que mostrar en GUI al iniciar el programa | 89 | | BITMAP_TYPE| Que campo debe enseñarse en el bitmap, `REGISTER` si registro o `MEMORY` si Memoria Principal| 90 | | BITMAP_ADDR| Direccion a coger como bitmap. Si es registro, muestra un registro 0-31 o en el caso de la MP, la palabra de la direccion| 91 | | TAG_INICIO| Etiqueta del inicio del programa "START" en el codigo fuente ensamblador | 92 | | TAG_BREAKPOINT| En caso de haber, punto de ruptura hasta el que ejecutar al iniciar la GUI, similar a SKIP_INICIO | 93 | 94 | Nota: En un sistema Windows, los Directorios deben ser especificados con doble barra invertida `\\` en lugar de una sola `/`, como lo esta en e `config.json` de ejemplo. 95 | Primero se ejecuta `TAG_BREAKPOINT` y luego `SKIP_INICIO`, por lo que es poosible poner un skip a partir de una etiqueta 96 | El bitmap muestra en binario una celda de la memoria o de los registros, no el valor en si. Si cambia la direccion de la memoria en dicha celda, tambien lo hace el bitmap. 97 | 98 | El arhivo `configEjemploWindows.json` sirve de configuracion de ejemplo de un sistema Windows. 99 | Esta configuracion asume haber descargado el contenido del [Emulador del MC88110 Proporcionado por el Departamento de Arquitectura y Sistemas Informáticos de la Facultad de Informática de la UPM](https://www.datsi.fi.upm.es/docencia/Estructura_09/Proyecto_Ensamblador/), renombrado la configuracion a `config.json` y desempaquetado sus contenidos en una carpeta emu en el mismo directorio que el ejecutable de la GUI, asi como que el codigo fuente es un archivo `cvd.ens` en la misma carpeta que el .jar de esta GUI. 100 | Tambien asume que las direcciones de memoria que se quieren traducir a ascii estan en la 4000, y que la memoria 4000 es la que se quiere ver en el bitmap. 101 | 102 | ## Ejecucion 103 | 104 | El proyecto esta escrito en Java 17, por tanto esta o versiones mas recientes deberian de poder ejecutarlo sin problemas. 105 | 106 | Se puede obtener un ejecutable .jar desde releases, o clonar la repo, abrir un IDE en el proyecto y ejecutar main desde me.bodiw.App 107 | 108 | Se requiere configurar el archivo `config.json`, dado que la GUI es un WRAPPER, no el emulador en si. 109 | 110 | Intentar no pasarle nombres "Graciosos", dado que la GUI parsea la salida del emulador. Meter "PC = 99999" por Stdin en algun otro modo es mas que capaz de confundir a la GUI. En general evitar patrones/nombres que use el Emulador en si 111 | 112 | En caso de problemas , se puede ejecutar desde una terminal con `java -jar estortura.jar miConfiguracion.json` para ver los mensajes de error a traves de consola. 113 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/process/AssemblerProcess.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.process; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.util.Map; 9 | 10 | import me.bodiw.App; 11 | import me.bodiw.Config; 12 | import me.bodiw.gui.ControlReg; 13 | import me.bodiw.interpreter.Interpreter; 14 | import me.bodiw.model.Word; 15 | 16 | public class AssemblerProcess implements AutoCloseable { 17 | 18 | public String emulator, conf, bin, lastCmd, nextInst, breakpoint_tag; 19 | public int stepsInicio, skipInicio; 20 | public double scale; 21 | 22 | Process proc; 23 | BufferedReader in; 24 | BufferedWriter out; 25 | public Word bitMap; 26 | 27 | public Word[][] regs; 28 | public Word[][] mem; 29 | public ControlReg[] controlRegs; // { pc, ti, ciclo, fl, fe, fc, fv, fr }; 30 | 31 | public int memAddress; 32 | 33 | public AssemblerProcess(Config cf) throws IOException { 34 | this.lastCmd = ""; 35 | 36 | proc = new ProcessBuilder(cf.emulator, "-c", cf.config, cf.bin).redirectErrorStream(true).start(); 37 | in = new BufferedReader(new InputStreamReader(proc.getInputStream())); 38 | out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())); 39 | 40 | String output = this.readFirst(); // Skip first config/lines 41 | 42 | if (output.contains("ERROR en lectura de datos")) { 43 | throw new RuntimeException("Error intentando leer la salida del emulador\n" + output); 44 | } 45 | 46 | memAddress = cf.memory_start - (cf.memory_start % 16); 47 | breakpoint_tag = cf.breakpoint; 48 | skipInicio = cf.skip_start; 49 | stepsInicio = cf.step_start; 50 | scale = cf.scale; 51 | 52 | controlRegs = new ControlReg[8]; 53 | regs = new Word[8][4]; 54 | mem = new Word[8][4]; 55 | 56 | for (int i = 0; i < 8; i++) { 57 | controlRegs[i] = new ControlReg(); 58 | } 59 | 60 | for (int i = 0; i < 8; i++) { 61 | for (int j = 0; j < 4; j++) { 62 | regs[i][j] = new Word(); 63 | mem[i][j] = new Word(); 64 | } 65 | } 66 | 67 | if (cf.bitmap_type == 0) { 68 | bitMap = regs[cf.bitmap_start / 4][cf.bitmap_start % 4]; 69 | } else if (cf.bitmap_type == 1) { 70 | cf.bitmap_start = cf.bitmap_start % 32; 71 | bitMap = mem[cf.bitmap_start / 4][cf.bitmap_start % 4]; 72 | } 73 | 74 | if (!breakpoint_tag.isEmpty()) { 75 | System.out.println("Running to " + breakpoint_tag + " breakpoint"); 76 | this.write("p + " + breakpoint_tag); 77 | this.read(); 78 | this.write("e"); 79 | } 80 | 81 | if (skipInicio > 0) { 82 | this.write("t " + skipInicio); 83 | this.read(); 84 | } 85 | } 86 | 87 | public String read() { 88 | StringBuilder s = new StringBuilder(700); 89 | do { 90 | try { 91 | while (!in.ready()) { // El pobre emulador es lentito 92 | Thread.sleep(5); 93 | } 94 | while (in.ready()) { 95 | s.append((char) in.read()); 96 | } 97 | } catch (IOException | InterruptedException e) { 98 | App.showError("Assembler reader", "Error intentando leer la salida del emulador\n" + e.getMessage()); 99 | e.printStackTrace(); 100 | } 101 | /* 102 | * El Stream se bloquea antes de tiempo ante procesos que requieran 103 | * un minimo de computacion y se reabre tarde. Dado que lo primero 104 | * que vuelve a escribir es el comando anterior, esperar a que haya 105 | * escrito el comando, line feed, salto de linea y proximo caracter 106 | * es la minima garantia de que el stream no estuviese bloqueado 107 | */ 108 | } while (!s.toString().contains("88110>")); 109 | 110 | return s.toString(); 111 | } 112 | 113 | public String readRegs() { 114 | this.writeSilent("r"); 115 | return this.read(); 116 | } 117 | 118 | public String readMem(int address) { 119 | this.writeSilent("v " + (address - (address % 16)) + " 32"); 120 | return this.read(); 121 | } 122 | 123 | public void writeSilent(String s) { 124 | try { 125 | out.write(s + "\n"); 126 | out.flush(); 127 | } catch (IOException e) { 128 | App.showError("Assembler writer", "Error intentando escribir al emulador\n" + e.getMessage()); 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | public void write(String s) { 134 | try { 135 | out.write(s + "\n"); 136 | out.flush(); 137 | this.lastCmd = s; 138 | } catch (IOException e) { 139 | App.showError("Assembler writer", "Error intentando escribir al emulador\n" + e.getMessage()); 140 | e.printStackTrace(); 141 | } 142 | } 143 | 144 | public void step(int steps) { 145 | this.write("t " + steps); 146 | this.read(); 147 | } 148 | 149 | public void updateRegs() { 150 | String s = this.readRegs(); 151 | Map values = Interpreter.readRegs(s); 152 | 153 | nextInst = (String) values.get("Instruction"); 154 | 155 | int cycle = (int) values.get("Cycle"); 156 | 157 | String[] controlStrings = { "PC", "TotalInstructions", "Cycle", "FL", "FE", "FC", "FV", "FR" }; 158 | 159 | for (int i = 0; i < 8; i++) { 160 | int newValue = (int) values.get(controlStrings[i]); 161 | if (controlRegs[i].value != newValue) { 162 | controlRegs[i].lastCycleUpdate = cycle; 163 | controlRegs[i].value = newValue; 164 | } 165 | } 166 | 167 | for (int i = 0; i < 8; i++) { 168 | for (int j = 0; j < 4; j++) { 169 | byte[] bytes = (byte[]) values.get(String.format("R%02d", i * 4 + j)); 170 | if (!regs[i][j].equals(bytes)) { 171 | regs[i][j].lastCycleUpdate = cycle; 172 | regs[i][j].data = bytes; 173 | } 174 | } 175 | } 176 | 177 | } 178 | 179 | public void updateMem() { 180 | String s = this.readMem(memAddress); 181 | Map values = Interpreter.readMem(s); 182 | 183 | int cycle = controlRegs[2].value; 184 | 185 | for (int i = 0; i < 8; i++) { 186 | byte[][] row = values.get(memAddress + i * 16); 187 | for (int j = 0; j < 4; j++) { 188 | byte[] bytes = (byte[]) row[j]; 189 | if (!mem[i][j].equals(bytes)) { 190 | mem[i][j].lastCycleUpdate = cycle; 191 | mem[i][j].data = bytes; 192 | } 193 | } 194 | } 195 | } 196 | 197 | @Override 198 | public void close() throws Exception { 199 | if (out != null) 200 | out.close(); 201 | if (in != null) 202 | in.close(); 203 | if (proc != null) 204 | proc.destroy(); 205 | } 206 | 207 | private String readFirst() { 208 | StringBuilder s = new StringBuilder(700); 209 | do { 210 | try { 211 | while (!in.ready()) { // El pobre emulador es lentito 212 | Thread.sleep(5); 213 | } 214 | while (in.ready()) { 215 | s.append((char) in.read()); 216 | } 217 | } catch (IOException | InterruptedException e) { 218 | App.showError("Assembler reader", "Error intentando leer la salida del emulador\n" + e.getMessage()); 219 | e.printStackTrace(); 220 | } 221 | } while (!s.toString().contains("88110>") && !s.toString().contains("ERROR en lectura de datos")); 222 | 223 | return s.toString(); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /ComoProgramarEnsamblador.md: -------------------------------------------------------------------------------- 1 | # Manual de programación en ensamblador 2 | 3 | La práctica de programación en ensamblador de Estructura de Computadores consiste en la creación de un compresor de texto. 4 | 5 | El emulador utilizado es el basado en el lenguaje del Motorola MC88110 6 | 7 | Asique para ayudar un poquito, vamos a ver cómo programar en ensamblador. 8 | 9 | --- 10 | 11 | ## De C a Ensamblador 12 | 13 | Con unos simples conceptos básicos, la programación en C es bastante ligera y amigable. 14 | Sin embargo, se mire como se mire, la programación en Ensamblador es bastante tortuosa. 15 | Es por ello, que el objetivo de cualquier implementación en ensamblador consiste en una implementación en C, junto a una traducción a ensamblador. 16 | Con unos pocos cambios de mentalidad, ensamblador puede ser ameno. 17 | 18 | --- 19 | 20 | ### Macros 21 | 22 | Una macro es una expansión de código en la fase de pre-procesado. Cada invocación a una macro en el código, será expandida en su completitud a todo el código en el binario final. 23 | Además, las macros aceptan argumentos, que serán sustituidos de manera literal por su contenido. Considera esto como un "copia y pega" del texto en el argumento al interior de la macro. 24 | 25 | ``` 26 | ; Declaración 27 | PUSH: MACRO (registro) 28 | subu r30, r30, 4 29 | st registro, r30, 0 30 | ENDMACRO 31 | ; Invocación 32 | PUSH(r10) 33 | ``` 34 | 35 | --- 36 | 37 | ### Bucles 38 | 39 | En cualquier idioma de programación, los bucles/iteraciones son un elemento esencial para las tareas repetitivas. Ensamblador no es excepción, asique analicemos la transformación de un clásico bucle `for` a un bucle en ensamblador. 40 | Debido a la no-existencia de bucles en ensamblador, la única manera que tenemos de trabajar en este escenario, es con la _keyword_ de C `goto`, que permite saltar a otro segmento de código de nuestro programa. Analicemos el funcionamiento de un bucle `for`, su estado intermedio, y por último su traducción a C, mediante un ejemplo de un [Cifrador César](https://es.wikipedia.org/wiki/Cifrado_C%C3%A9sar), en el cuál un texto en claro pasa a ser cifrado mediante una operación `c = (m + k) mod(a)`, donde c es el carácter(valor en ascii) cifrado final, m es el carácter original, a es el numero de caracteres en el alfabeto y k es la llave o "contraseña" de nuestro cifrado. 41 | 42 | ```c 43 | char *text = "mensajesupersecreto\0"; 44 | char *ciphertext; 45 | int key = 3; 46 | 47 | for(int i = 0; i<20; i++){ 48 | ciphertext[i] = ((text[i] - 'a' + key) % 26) + 'a'; 49 | } 50 | ``` 51 | 52 | En este escenario, estamos iterando sobre los 20 caracteres de text (el `null terminator \0` no cuenta lógicamente como parte de la cadena). Convertimos el valor ascii del texto a un numero de 0-26 para representar el valor en el abecedario, realizamos el encriptado, y volvemos a convertir a ascii. 53 | Sin embargo, este es un problema mejor formulado con un bucle while, y notación de punteros en lugar de arrays. El siguiente segmento de código tiene la misma funcionalidad: 54 | 55 | ```c 56 | char *text = "mensajesupersecreto\0"; 57 | char *ciphertext; 58 | int i = 0, key = 3; 59 | 60 | while((text + i)* != '\0'){ 61 | (ciphertext + i)* = (((text + i)* - 'a' + key) % 26) + 'a'; 62 | i++; 63 | } 64 | ``` 65 | 66 | Ahora tenemos algo más similar a lo que ocurre en realidad,y no tenemos que contar las letras del texto. 67 | 68 | Accedemos a la dirección de las cadenas con un offset i para extraer o guardar valores de la operación de encriptado. 69 | 70 | Hasta ahora, el código es literalmente el mismo, solo que escrito de otro modo. 71 | Pero sigue sin ser suficiente, asique vamos a eliminar el uso de `for` y `while` mediante `goto`. Aunque antes de proceder a ello, descompongamos el funcionamiento de estos: 72 | 73 | ```c 74 | for(; ; ){ 75 | 76 | } 77 | ``` 78 | 79 | ```c 80 | 81 | while(){ 82 | 83 | 84 | } 85 | ``` 86 | 87 | Se nota ya un patrón de como funcionan los bucles, no? Pues procedamos a reescribirlos con `goto` y `tags`: 88 | 89 | ```c 90 | 91 | goto condicion; 92 | bucle: 93 | 94 | 95 | condicion: 96 | if () 97 | goto bucle; 98 | ``` 99 | 100 | Veamos ahora el funcionamiento de este segmento: 101 | 102 | 1. Declaramos la variable local 103 | 2. Saltamos a la condición del bucle, ignorando el código de por medio 104 | 1. Si la condición es verdadera, saltamos de nuevo hacia el inicio del código de dentro del bucle y ejecutamos la primera iteración 105 | 2. Al terminar el código, ejecutamos nuestra sentencia de final de iteración (por lo general es i++) 106 | 3. Analizamos de nuevo la condición del bucle para ver si iteramos de nuevo 107 | 3. Si la condición es falsa, se ignora el goto y el código continua sin haber ejecutado ninguna iteración. 108 | 109 | Ahora, explicado el esquema anterior, procedamos a transformar nuestro cifrado césar: 110 | 111 | ```c 112 | char *text = "mensajesupersecreto\0"; 113 | char *ciphertext; 114 | int i = 0, key = 3; 115 | 116 | goto condicion; 117 | bucle: 118 | (ciphertext + i)* = (((text + i)* - 'a' + key) % 26) + 'a'; 119 | i++; 120 | condicion: 121 | if((text + i)* != '\0') 122 | goto bucle; 123 | ``` 124 | 125 | Enhorabuena! Acabas de entender como funciona un bucle a bajo nivel. 126 | Aunque aún tenemos que bajar un poco más para poder decir que este código es idéntico a ensamblador. La línea que contiene la operación de cifrado tiene demasiadas operaciones, asique vamos a tener que descomponer el bucle un poco más, de tal modo que cada línea contenga una única operación. 127 | 128 | ```c 129 | char *text = "mensajesupersecreto\0"; 130 | char *ciphertext; 131 | int i = 0; 132 | int key = 3; 133 | int aux; 134 | 135 | goto condicion; 136 | bucle: 137 | // Referencia: 138 | // (ciphertext + i)* = (((text + i)* - 'a' + key) % 26) + 'a'; 139 | aux = aux - 'a'; 140 | aux = aux + key; 141 | MOD(aux, 26); // Realizamos la operacion modulo con una macro que no vamos a implementar aqui, que en ensamblador no hay instrucción "modulo" 142 | aux = aux + 'a'; 143 | (ciphertext + i)* = aux; // Recuerdas lo de que con arrays, punteros y memoria se hace por separado? Pues eso 144 | i = i + 1; 145 | condicion: 146 | // OJO: Esta es la primera comparación, ademas asignamos a aux_a 147 | aux = (text + i)*; // Guardamos en aux el carácter actual del texto sin cifrar 148 | // Importante notar que accesos y escrituras a memoria/arrays se hacen por separado 149 | if(aux != '\0') // Que no se cumple la condición? ignora el goto 150 | goto bucle; // Se cumple? A iterar 151 | ``` 152 | 153 | Y ya está, tenemos el bucle traducido. Hay margen de optimización, modulo estará implementado en una macro por separado, pero está listo para el paso final 154 | 155 | Antes de proceder, pongamos unas condiciones para el set de instrucciones: 156 | 157 | 1. Solo contamos con 27 variables (registros), r2...28 158 | 2. Las comparaciones requieren de un registro auxiliar para el resultado 159 | 3. Los ascii necesitan un valor literal (el numerito, vamos) 160 | 161 | Asique con esto montado, elijamos unos registros cualesquiera que usar y su finalidad, así como el set de instrucciones 162 | 163 | | Registro | Contenido | 164 | | -------- | ------------------------------- | 165 | | r5 | Puntero a Texto sin cifrar | 166 | | r6 | Puntero a Texto cifrado | 167 | | r7 | i | 168 | | r10 | key | 169 | | r15 | aux | 170 | | r28 | Registo temporal de comparación | 171 | 172 | Y el set de instrucciones: 173 | 174 | | Instrucción | Sintaxis | Operación | 175 | | ----------- | --------------------------- | -------------------------------------------------------------------- | 176 | | addu | addu rD,r1,(r2 \| N) | Suma sin signo | 177 | | subu | subu rD,r1,(r2 \| N) | Resta sin signo | 178 | | st | st rD, r1, r2 | Store(guardar en Memoria principal/Array) contenido de rD en r1 + r2 | 179 | | ld | ld rD, r1, r2 | Load(sacar de Memoria principal/Array) contenido de r1 + r2 en rD | 180 | | cmp | cmp rD, r1, (r2 \| N) | Comparación en rD de r1 y r2 | 181 | | bb1 | bb1 op, rD, (tag \| N \ r1) | branch bit 1 (salta si el bit op está a 1) | 182 | | or | or rD, r1, r2 | Operación OR bit a bit | 183 | | br | br (tag \| r1) | Salta r1\*4 instrucciones | 184 | 185 | Listo! Vamos allá! 186 | 187 | ```ens 188 | ; Macros disponibles: MOD, LEA, PUSH, POP 189 | 190 | ; Declara la cadena original en memoria 191 | text: "mensajesupersecreto\0" 192 | 193 | ; Declaración(inicialización) de variables 194 | LEA(r5, text); La direccion de una tag se guarda con LEA 195 | or r6, r0, 0x100; Guardamos en 0x100 la cadena cifrada 196 | or r7, r0, 0; Inicializamos i a 0 197 | or r10, r0, 3; Inicializamos la llave a 3 198 | or r15, r0, 0; Inicializamos aux a 0 199 | 200 | br condicion 201 | 202 | bucle: 203 | subu r15, r15, 97; Convertimos aux a un numero de 0-26 204 | addu r15, r15, r10; aux = aux + key 205 | MOD(r15, 26); aux = aux % 26 206 | addu r15, r15, 97; Convertimos aux de vuelta a ascii 207 | st r15, r6, r7; (ciphertext + i)* = aux 208 | addu r7, r7, 1; i++ 209 | 210 | condicion: 211 | ld r15, r5, r7; Guardamos en aux el carácter actual del texto sin cifrar 212 | cmp r28, r15, 0; Comparamos aux con '\0' 213 | bb1 ne, r28, bucle; Si aux != '\0', salta a bucle 214 | 215 | ``` 216 | 217 | Eso es todo! Ya tenemos el bucle traducido, sabemos qué instrucciones usar para replicar las operaciones que hubiesemos usado en C, y con la mentalidad de este problema, podemos atacar cualquier reto en ensamblador 218 | 219 | Por ultimo, antes de proceder, veamos algunas instrucciones del MC88110, y cómo se usan 220 | 221 | --- 222 | 223 | ## Instruction Set 224 | 225 | ### Instrucciones Lógicas 226 | 227 | Considera cada operando de la operación como un arrays de bits, y el array resultado es almacenado en rD 228 | 229 | | Instrucción | Sintaxis | Operación | 230 | | ----------- | ------------------- | ----------------------- | 231 | | and | and rD,r1,(r2 \| N) | Operación AND bit a bit | 232 | | or | or rD,r1,(r2 \| N) | Operación OR bit a bit | 233 | | xor | xor rD,r1,(r2 \| N) | Operación XOR bit a bit | 234 | 235 | Un ejemplo es el siguiente: `or r3, r2(con valor 25), 10`, que realizaría una operación `r3 = 27 = b00011001 | b00001010` 236 | 237 | ### Instrucciones Aritméticas 238 | 239 | | Instrucción | Sintaxis | Operación | 240 | | ----------- | -------------------- | ------------------------ | 241 | | addu | addu rD,r1,(r2 \| N) | Suma sin signo | 242 | | subu | subu rD,r1,(r2 \| N) | Resta sin signo | 243 | | mulu | mulu rD,r1,(r2 \| N) | Multiplicación sin signo | 244 | | divu | divu rD,r1,(r2 \| N) | División sin signo | 245 | | sub | sub rD,r1,(r2 \| N) | Resta con signo | 246 | | cmp | cmp rD,r1,(r2 \| N) | Comparación | 247 | 248 | ### Instrucciones de Campo de Bit 249 | 250 | Al igual que con las instrucciones lógicas, consideraremos los registros y sus contenidos como arrays de bits, que facilitan el entendimiento de la funcionalidad de las instrucciones. 251 | La sintaxis `W5<05>` se refiere a una sección de tamaño _WIDTH_ especificado por 5 bits(0-32), con un desplazamiento _OFFSET_ de 5 bits, osea, un caso particular `2<7>` implica seleccionar 2 bits a partir del bit 7. 252 | 253 | Cada W5<05> puede ser reemplazado por un registro, cuyo contenido será interpretado, extrayendo el valor O5 de los 5 bits menos significativos, y W5 de los bits 10-5 254 | 255 | ```ens 256 | ; W5 = 2<7> 257 | ; |---| 258 | ; 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1|1 1|1 1 1 1 1 1 1 259 | ; |---| 260 | ; Little Endian 31-> 30-> 29->...-> 2-> 1-> 0 261 | ``` 262 | 263 | | Instrucción | Sintaxis | Operación | 264 | | ----------- | ------------------------------------- | ------------------------------------------------------------------------------------------- | 265 | | clr | clr rD, r1, (WIDTH5\ \| r2) | Guarda en rD r1 con el campo de bits a 0 | 266 | | set | set rD, r1, (WIDTH5\ \| r2) | Guarda en rD r1 con el campo de bits a 1 | 267 | | ext | ext rD, r1, (WIDTH5\ \| r2) | Guarda en los bits menos significativos de rD el campo de bits de r1 con extensión de signo | 268 | | extu | extu rD, r1, (WIDTH5\ \| r2) | Guarda en los bits menos significativos de rD el campo de bits de r1 sin extensión de signo | 269 | | mak | mak rD, r1, (WIDTH5\ \| r2) | Guarda los OFFSET bits menos significativos de r1 con desplazamiento WIDTH en rD | 270 | | rot | rot rD, r1, (\ \| r2) | Guarda en rD los bits de r1 rotados a la derecha OFFSET veces | 271 | 272 | ### Instrucciones de Control de flujo 273 | 274 | | Instrucción | Sintaxis | Operación | 275 | | ----------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | 276 | | br | br (r1 \| tag \| N) | Salta a la tag o dirección de PC + (r1 \| N) \* 4 instrucciones | 277 | | bb1 | bb1 op, r1, (tag \| N \| r1) | Salta si el bit op está a 1 en r1 a la tag o dirección de PC + (r1 \| N) \* 4 instrucciones | 278 | | bb0 | bb0 op, r1, (tag \| N \| r1) | Salta si el bit op está a 0 en r1 a la tag o dirección de PC + (r1 \| N) \* 4 instrucciones | 279 | | bsr | bsr (r1 \| tag \| N) | Salta a la tag o dirección de PC + (r1 \| N) \* 4 instrucciones y además guarda el PC actual + 4 en r1 (osea, la siguiente instrucción) | 280 | 281 | ### Instrucciones de Carga y Almacenamiento 282 | 283 | | Instrucción | Sintaxis | Operación | 284 | | ----------- | ---------------- | -------------------------------------------------------------------------------------- | 285 | | ld | ld rD, r1, r2 | Guarda en rD el contenido de la dirección r1 + r2 | 286 | | st | st rD, r1, r2 | Guarda en la dirección r1 + r2 el contenido de rD | 287 | | ld.bu | ld.bu rD, r1, r2 | Guarda en rD el contenido (byte menos significativo) de la dirección r1 + r2 sin signo | 288 | | st.b | st.b rD, r1, r2 | Guarda en la dirección r1 + r2 el byte menos significativo de rD | 289 | 290 | --- 291 | -------------------------------------------------------------------------------- /src/main/java/me/bodiw/gui/Gui.java: -------------------------------------------------------------------------------- 1 | package me.bodiw.gui; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.Font; 5 | import java.awt.GridBagConstraints; 6 | import java.awt.GridBagLayout; 7 | import java.awt.Insets; 8 | import java.awt.event.ActionEvent; 9 | import java.awt.event.ActionListener; 10 | import java.awt.event.KeyAdapter; 11 | import java.awt.event.KeyEvent; 12 | import java.awt.event.MouseAdapter; 13 | import java.awt.event.MouseEvent; 14 | import java.awt.event.MouseWheelEvent; 15 | import java.awt.event.MouseWheelListener; 16 | 17 | import javax.swing.BorderFactory; 18 | import javax.swing.BoxLayout; 19 | import javax.swing.GroupLayout; 20 | import javax.swing.JButton; 21 | import javax.swing.JFrame; 22 | import javax.swing.JLabel; 23 | import javax.swing.JPanel; 24 | import javax.swing.JScrollPane; 25 | import javax.swing.JSpinner; 26 | import javax.swing.JTabbedPane; 27 | import javax.swing.JTextArea; 28 | import javax.swing.JTextField; 29 | import javax.swing.SpinnerNumberModel; 30 | import javax.swing.SwingConstants; 31 | import javax.swing.WindowConstants; 32 | 33 | import me.bodiw.App; 34 | import me.bodiw.Config; 35 | import me.bodiw.model.Word; 36 | import me.bodiw.process.AssemblerProcess; 37 | 38 | /** 39 | * 40 | * @author bogdan (con ayudita de NetBeans) 41 | */ 42 | public class Gui extends JFrame { 43 | 44 | private WordLabel[][] registerWords; 45 | private WordLabel[][] memWords; 46 | private AsciiLabel[][] asciiMemWords; 47 | private AsciiLabel[][] asciiRegWords; 48 | private ControlRegLabel[] controlRegs; 49 | private JLabel[] registerLabels; 50 | private JPanel[] registerRows; 51 | private JLabel[] memLabels; 52 | private JPanel[] memRows; 53 | private JPanel[] asciiRegRows; 54 | private JPanel[] asciiMemRows; 55 | private JLabel[] bitLabels; 56 | 57 | private JTabbedPane tabRegistros; 58 | private JPanel panelRegistros; 59 | private JScrollPane stdout; 60 | private JTextArea stdoutpane; 61 | private JTabbedPane asciireg; 62 | private JPanel asciiRegPanel; 63 | private JTabbedPane mem; 64 | private JPanel memoria; 65 | private JTabbedPane controltab; 66 | private JPanel controlpanel; 67 | private JPanel Instrucciones; 68 | private JLabel last; 69 | private JLabel next; 70 | private JLabel lastval; 71 | private JLabel nextval; 72 | private JPanel conf; 73 | private JSpinner stepspinner; 74 | private JSpinner memspinner; 75 | private JButton membutton; 76 | private JButton stepbutton; 77 | private JButton stdinbutton; 78 | private JButton reloadButton; 79 | private JTextField stdinval; 80 | private JTabbedPane asciimem; 81 | private JPanel asciiMemPanel; 82 | private JPanel bitTabPanel; 83 | private JTabbedPane bitTab; 84 | 85 | private AssemblerProcess assembler; 86 | 87 | private float scale = 1; 88 | 89 | public Gui(String name, AssemblerProcess assembler) { 90 | super(name); 91 | this.assembler = assembler; 92 | initComponents(); 93 | } 94 | 95 | private void initComponents() { 96 | 97 | registerWords = new WordLabel[8][4]; 98 | memWords = new WordLabel[8][4]; 99 | asciiRegWords = new AsciiLabel[8][4]; 100 | asciiMemWords = new AsciiLabel[8][4]; 101 | controlRegs = new ControlRegLabel[8]; // { pc, ti, ciclo, fl, fe, fc, fv, fr }; 102 | registerLabels = new JLabel[8]; 103 | registerRows = new JPanel[8]; 104 | memLabels = new JLabel[8]; 105 | memRows = new JPanel[8]; 106 | asciiRegRows = new JPanel[8]; 107 | asciiMemRows = new JPanel[8]; 108 | 109 | GridBagConstraints gridBagConstraints; 110 | 111 | tabRegistros = new JTabbedPane(); 112 | panelRegistros = new JPanel(); 113 | stdout = new JScrollPane(); 114 | stdoutpane = new JTextArea(); 115 | asciireg = new JTabbedPane(); 116 | asciiRegPanel = new JPanel(); 117 | mem = new JTabbedPane(); 118 | memoria = new JPanel(); 119 | controltab = new JTabbedPane(); 120 | controlpanel = new JPanel(); 121 | Instrucciones = new JPanel(); 122 | last = new JLabel(); 123 | next = new JLabel(); 124 | lastval = new JLabel(); 125 | nextval = new JLabel(); 126 | conf = new JPanel(); 127 | stepspinner = new JSpinner(); 128 | memspinner = new JSpinner(); 129 | membutton = new JButton(); 130 | stepbutton = new JButton(); 131 | stdinbutton = new JButton(); 132 | stdinval = new JTextField(); 133 | asciimem = new JTabbedPane(); 134 | asciiMemPanel = new JPanel(); 135 | bitTabPanel = new JPanel(); 136 | bitTab = new JTabbedPane(); 137 | reloadButton = new JButton(); 138 | bitLabels = new JLabel[32]; 139 | 140 | scale = assembler.scale; 141 | 142 | Dimension dimension_400_19 = new Dimension((int) (scale * 400), (int) (scale * 19)); 143 | Dimension dimension_100_19 = new Dimension((int) (scale * 100), (int) (scale * 19)); 144 | Dimension dimension_60_19 = new Dimension((int) (scale * 60), (int) (scale * 19)); 145 | Dimension dimension_34_19 = new Dimension((int) (scale * 34), (int) (scale * 19)); 146 | Dimension dimension_192_19 = new Dimension((int) (scale * 192), (int) (scale * 19)); 147 | Dimension dimension_100_38 = new Dimension((int) (scale * 100), (int) (scale * 38)); 148 | Dimension dimension_114_38 = new Dimension((int) (scale * 114), (int) (scale * 38)); 149 | Dimension dimension_68_38 = new Dimension((int) (scale * 68), (int) (scale * 38)); 150 | Dimension dimension_70_38 = new Dimension((int) (scale * 70), (int) (scale * 38)); 151 | Dimension dimension_68_25 = new Dimension((int) (scale * 68), (int) (scale * 25)); 152 | Dimension dimension_73_25 = new Dimension((int) (scale * 73), (int) (scale * 25)); 153 | Dimension dimension_442_187 = new Dimension((int) (scale * 442), (int) (scale * 187)); 154 | Dimension dimension_179_19 = new Dimension((int) (scale * 179), (int) (scale * 19)); 155 | Dimension dimension_35_19 = new Dimension((int) (scale * 35), (int) (scale * 19)); 156 | Dimension dimension_19_19 = new Dimension((int) (scale * 19), (int) (scale * 19)); 157 | Dimension dimension_19_24 = new Dimension((int) (scale * 19), (int) (scale * 24)); 158 | 159 | Font cantarell_10 = new Font("Cantarell", 0, (int) (scale * 10)); 160 | Font cantarell_14 = new Font("Cantarell", 0, (int) (scale * 14)); 161 | Font cantarell_15 = new Font("Cantarell", 0, (int) (scale * 15)); 162 | Font monospaced_13 = new Font("Monospaced", 0, (int) (scale * 13)); 163 | 164 | setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 165 | 166 | tabRegistros.setMaximumSize(dimension_442_187); 167 | 168 | panelRegistros.setLayout(new GridBagLayout()); 169 | panelRegistros.setBackground(Colors.BACKGROUND); 170 | panelRegistros.setForeground(Colors.FOREGROUND); 171 | 172 | memoria.setBackground(Colors.BACKGROUND); 173 | memoria.setForeground(Colors.FOREGROUND); 174 | 175 | asciiMemPanel.setBackground(Colors.BACKGROUND); 176 | asciiMemPanel.setForeground(Colors.FOREGROUND); 177 | 178 | asciiRegPanel.setBackground(Colors.BACKGROUND); 179 | asciiRegPanel.setForeground(Colors.FOREGROUND); 180 | 181 | controlpanel.setBackground(Colors.BACKGROUND); 182 | controlpanel.setForeground(Colors.FOREGROUND); 183 | 184 | Instrucciones.setBackground(Colors.BACKGROUND); 185 | Instrucciones.setForeground(Colors.FOREGROUND); 186 | 187 | conf.setBackground(Colors.BACKGROUND); 188 | conf.setForeground(Colors.FOREGROUND); 189 | 190 | stdout.setBackground(Colors.BACKGROUND); 191 | stdout.setForeground(Colors.FOREGROUND); 192 | 193 | stdoutpane.setBackground(Colors.BACKGROUND); 194 | stdoutpane.setForeground(Colors.FOREGROUND); 195 | 196 | bitTabPanel.setBackground(Colors.BACKGROUND); 197 | bitTabPanel.setForeground(Colors.FOREGROUND); 198 | 199 | this.getContentPane().setBackground(Colors.BACKGROUND); 200 | 201 | for (int i = 0; i < 8; i++) { // Etiquetas R XX 202 | JLabel label = new JLabel(); 203 | registerLabels[i] = label; 204 | Dimension size = dimension_34_19; 205 | label.setBackground(panelRegistros.getBackground()); 206 | label.setForeground(panelRegistros.getForeground()); 207 | label.setHorizontalAlignment(SwingConstants.CENTER); 208 | label.setText(String.format("R %02d", i * 4)); 209 | label.setBorder(Colors.BORDER); 210 | label.setMaximumSize(size); 211 | label.setMinimumSize(size); 212 | label.setPreferredSize(size); 213 | label.setFont(cantarell_15); 214 | gridBagConstraints = new GridBagConstraints(); 215 | gridBagConstraints.gridx = 0; 216 | gridBagConstraints.ipadx = 8; 217 | panelRegistros.add(label, gridBagConstraints); 218 | } 219 | 220 | for (int i = 0; i < 8; i++) { // Filas de los registro 221 | JPanel registerRow = new JPanel(); 222 | registerRows[i] = registerRow; 223 | Dimension size = dimension_400_19; 224 | BoxLayout layout = new BoxLayout(registerRow, BoxLayout.X_AXIS); 225 | registerRow.setBorder(Colors.BORDER); 226 | registerRow.setBackground(panelRegistros.getBackground()); 227 | registerRow.setForeground(panelRegistros.getForeground()); 228 | registerRow.setMaximumSize(size); 229 | registerRow.setMinimumSize(size); 230 | registerRow.setPreferredSize(size); 231 | registerRow.setLayout(layout); 232 | 233 | for (int j = 0; j < 4; j++) { // Columnas de los registros 234 | WordLabel label = new WordLabel(assembler.regs[i][j]); 235 | registerWords[i][j] = label; 236 | Dimension labelSize = dimension_100_19; 237 | label.setHorizontalAlignment(SwingConstants.CENTER); 238 | label.setText(label.word.toString()); 239 | label.setFont(cantarell_15); 240 | label.setMaximumSize(labelSize); 241 | label.setMinimumSize(labelSize); 242 | label.setPreferredSize(labelSize); 243 | label.setBackground(panelRegistros.getBackground()); 244 | label.setForeground(panelRegistros.getForeground()); 245 | label.addMouseListener(new MouseAdapter() { 246 | public void mousePressed(MouseEvent evt) { 247 | changeBitmapMouseEvent(evt); 248 | } 249 | }); 250 | 251 | registerRow.add(label); 252 | } 253 | gridBagConstraints = new GridBagConstraints(); 254 | gridBagConstraints.gridx = 1; 255 | panelRegistros.add(registerRow, gridBagConstraints); 256 | } 257 | 258 | tabRegistros.addTab("Registros", panelRegistros); 259 | tabRegistros.setEnabledAt(0, false); 260 | 261 | /* 262 | * MEMORIA PRINCIPAL 263 | */ 264 | 265 | mem.setMaximumSize(dimension_442_187); 266 | 267 | memoria.setLayout(new GridBagLayout()); 268 | 269 | for (int i = 0; i < 8; i++) { // Etiquetas XXXX 270 | JLabel label = new JLabel(); 271 | memLabels[i] = label; 272 | Dimension size = dimension_34_19; 273 | label.setBackground(memoria.getBackground()); 274 | label.setForeground(memoria.getForeground()); 275 | label.setHorizontalAlignment(SwingConstants.CENTER); 276 | label.setText(String.format("%4d", assembler.memAddress + i * 16)); 277 | label.setBorder(Colors.BORDER); 278 | label.setMaximumSize(size); 279 | label.setMinimumSize(size); 280 | label.setPreferredSize(size); 281 | label.setFont(cantarell_15); 282 | gridBagConstraints = new GridBagConstraints(); 283 | gridBagConstraints.gridx = 0; 284 | gridBagConstraints.ipadx = 8; 285 | memoria.add(label, gridBagConstraints); 286 | } 287 | 288 | for (int i = 0; i < 8; i++) { // Filas de la memoria 289 | JPanel memRow = new JPanel(); 290 | memRows[i] = memRow; 291 | Dimension size = dimension_400_19; 292 | BoxLayout layout = new BoxLayout(memRow, BoxLayout.X_AXIS); 293 | memRow.setBackground(memoria.getBackground()); 294 | memRow.setForeground(memoria.getForeground()); 295 | memRow.setBorder(Colors.BORDER); 296 | memRow.setMaximumSize(size); 297 | memRow.setMinimumSize(size); 298 | memRow.setPreferredSize(size); 299 | memRow.setLayout(layout); 300 | 301 | for (int j = 0; j < 4; j++) { // Columnas de la memoria 302 | WordLabel label = new WordLabel(assembler.mem[i][j]); 303 | memWords[i][j] = label; 304 | Dimension labelSize = dimension_100_19; 305 | label.setHorizontalAlignment(SwingConstants.CENTER); 306 | label.setText(label.word.toString()); 307 | label.setMaximumSize(labelSize); 308 | label.setMinimumSize(labelSize); 309 | label.setPreferredSize(labelSize); 310 | label.setBackground(memoria.getBackground()); 311 | label.setForeground(memoria.getForeground()); 312 | label.setFont(cantarell_15); 313 | label.addMouseListener(new MouseAdapter() { 314 | public void mousePressed(MouseEvent evt) { 315 | changeBitmapMouseEvent(evt); 316 | } 317 | }); 318 | memRow.add(label); 319 | } 320 | gridBagConstraints = new GridBagConstraints(); 321 | gridBagConstraints.gridx = 1; 322 | memoria.add(memRow, gridBagConstraints); 323 | } 324 | 325 | mem.addTab("Memoria", memoria); 326 | 327 | stdoutpane.setColumns(20); 328 | stdoutpane.setFont(cantarell_10); 329 | stdoutpane.setRows(5); 330 | stdoutpane.setText("88110 >"); 331 | stdoutpane.setEditable(false); 332 | stdout.setViewportView(stdoutpane); 333 | 334 | mem.addTab("Stdout", stdout); 335 | 336 | /* 337 | * Registros ASCII 338 | */ 339 | asciireg.setMaximumSize(dimension_442_187); 340 | 341 | asciiRegPanel.setLayout(new BoxLayout(asciiRegPanel, BoxLayout.Y_AXIS)); 342 | 343 | for (int i = 0; i < 8; i++) { // Filas de registros ascii 344 | JPanel asciiRegRow = new JPanel(); 345 | asciiRegRows[i] = asciiRegRow; 346 | Dimension size = dimension_179_19; 347 | GridBagLayout layout = new GridBagLayout(); 348 | asciiRegRow.setBackground(asciiMemPanel.getBackground()); 349 | asciiRegRow.setForeground(asciiMemPanel.getForeground()); 350 | asciiRegRow.setBorder(Colors.BORDER); 351 | asciiRegRow.setMaximumSize(size); 352 | asciiRegRow.setMinimumSize(size); 353 | asciiRegRow.setPreferredSize(size); 354 | asciiRegRow.setLayout(layout); 355 | 356 | for (int j = 0; j < 4; j++) { // Columnas de registros ascii 357 | AsciiLabel label = new AsciiLabel(assembler.regs[i][j]); 358 | asciiRegWords[i][j] = label; 359 | Dimension labelSize = dimension_35_19; 360 | 361 | label.setFont(monospaced_13); // NOI18N 362 | label.setHorizontalAlignment(SwingConstants.CENTER); 363 | label.setForeground(asciiRegRow.getForeground()); 364 | label.setBackground(asciiRegRow.getBackground()); 365 | label.setText("...."); 366 | label.setMaximumSize(labelSize); 367 | label.setMinimumSize(labelSize); 368 | label.setPreferredSize(labelSize); 369 | label.addMouseListener(new MouseAdapter() { 370 | public void mousePressed(MouseEvent evt) { 371 | changeBitmapMouseEvent(evt); 372 | } 373 | }); 374 | gridBagConstraints = new GridBagConstraints(); 375 | gridBagConstraints.ipadx = 8; 376 | asciiRegRow.add(label, gridBagConstraints); 377 | } 378 | gridBagConstraints = new GridBagConstraints(); 379 | gridBagConstraints.gridx = 1; 380 | asciiRegPanel.add(asciiRegRow, gridBagConstraints); 381 | } 382 | 383 | asciireg.addTab("Ascii", asciiRegPanel); 384 | asciireg.setEnabledAt(0, false); 385 | controltab.setMaximumSize(dimension_442_187); 386 | controlpanel.setLayout(new GridBagLayout()); 387 | 388 | String[] names = { "PC", "TI", "Ciclo", "FL", "FE", "FC", "FV", "FR" }; 389 | String[] tooltips = { 390 | "Program Counter\n Direccion de Memoria del Contador de Programa", 391 | "Total Instrucciones", "Ciclo de Reloj", 392 | "Flag: Little Endian\n 0 => Big Endian\n 1 => Little Endian", 393 | "Flag: Exceptions\n 0 => Excepciones Activas\n 1 => Excepciones Inhibidas", 394 | "Flag: Courriage (Acarreo)\n 0 => No ha habido Acarreo\n 1 => Ha habido Acarreo", 395 | "Flag: Overflow (desbordamiento)\n 0 => No ha habido Overflow\n 1 => Ha habido Overflow", 396 | "Flag: Round (Redondeo)\n 0 => Redondeo al mas cercano\n 1 => Redondeo hacia 0\n 2 => Redondeo hacia -Inf\n 3 => Redondeo hacia +Inf" }; 397 | 398 | for (int i = 0; i < 8; i++) { // Etiquetas Registros de Control 399 | JLabel label = new JLabel(); 400 | Dimension size = dimension_34_19; 401 | label.setHorizontalAlignment(SwingConstants.CENTER); 402 | label.setForeground(controlpanel.getForeground()); 403 | label.setBackground(controlpanel.getBackground()); 404 | label.setText(names[i]); 405 | label.setToolTipText(tooltips[i]); 406 | label.setBorder(Colors.BORDER); 407 | label.setMaximumSize(size); 408 | label.setMinimumSize(size); 409 | label.setPreferredSize(size); 410 | label.setFont(cantarell_15); 411 | gridBagConstraints = new GridBagConstraints(); 412 | gridBagConstraints.gridx = 1; 413 | gridBagConstraints.ipadx = 8; 414 | controlpanel.add(label, gridBagConstraints); 415 | } 416 | 417 | for (int i = 0; i < 8; i++) { // Valores Registros de Control 418 | ControlRegLabel label = new ControlRegLabel(assembler.controlRegs[i]); 419 | controlRegs[i] = label; 420 | Dimension size = dimension_60_19; 421 | label.setHorizontalAlignment(SwingConstants.CENTER); 422 | label.setForeground(controlpanel.getForeground()); 423 | label.setBackground(controlpanel.getBackground()); 424 | label.setText("" + label.reg.value); 425 | label.setBorder(Colors.BORDER); 426 | label.setMaximumSize(size); 427 | label.setMinimumSize(size); 428 | label.setPreferredSize(size); 429 | label.setFont(cantarell_15); 430 | gridBagConstraints = new GridBagConstraints(); 431 | gridBagConstraints.gridx = 0; 432 | controlpanel.add(label, gridBagConstraints); 433 | } 434 | 435 | /* 436 | * Mapa de bits 437 | */ 438 | bitTabPanel.setLayout(new GridBagLayout()); 439 | 440 | for (int i = 31; i >= 0; i--) { 441 | JLabel label = new JLabel(); 442 | JLabel value = new JLabel(); 443 | 444 | bitLabels[i] = value; 445 | 446 | label.setHorizontalAlignment(SwingConstants.CENTER); 447 | label.setText("" + i); 448 | label.setBorder(Colors.BORDER); 449 | label.setMaximumSize(dimension_19_19); 450 | label.setMinimumSize(dimension_19_19); 451 | label.setPreferredSize(dimension_19_19); 452 | label.setBackground(bitTabPanel.getBackground()); 453 | label.setForeground(bitTabPanel.getForeground()); 454 | label.setFont(cantarell_14); 455 | gridBagConstraints = new GridBagConstraints(); 456 | gridBagConstraints.gridy = 0; 457 | bitTabPanel.add(label, gridBagConstraints); 458 | 459 | value.setHorizontalAlignment(SwingConstants.CENTER); 460 | value.setText("0"); 461 | value.setBorder(Colors.BORDER); 462 | value.setMaximumSize(dimension_19_24); 463 | value.setMinimumSize(dimension_19_24); 464 | value.setPreferredSize(dimension_19_24); 465 | value.setBackground(bitTabPanel.getBackground()); 466 | value.setForeground(bitTabPanel.getForeground()); 467 | value.setFont(cantarell_14); 468 | value.setOpaque(true); 469 | gridBagConstraints = new GridBagConstraints(); 470 | gridBagConstraints.gridy = 1; 471 | bitTabPanel.add(value, gridBagConstraints); 472 | } 473 | 474 | bitTab.addTab("Bitmap", bitTabPanel); 475 | bitTab.setEnabledAt(0, false); 476 | 477 | controltab.addTab("Control", controlpanel); 478 | controltab.setEnabledAt(0, false); 479 | 480 | Instrucciones.setLayout(new GridBagLayout()); 481 | 482 | last.setHorizontalAlignment(SwingConstants.CENTER); 483 | last.setText("Last"); 484 | last.setToolTipText("Ultima Instruccion"); 485 | last.setBorder(Colors.BORDER); 486 | last.setMaximumSize(dimension_34_19); 487 | last.setMinimumSize(dimension_34_19); 488 | last.setPreferredSize(dimension_34_19); 489 | last.setForeground(Instrucciones.getForeground()); 490 | last.setBackground(Instrucciones.getBackground()); 491 | gridBagConstraints = new GridBagConstraints(); 492 | gridBagConstraints.gridx = 0; 493 | gridBagConstraints.ipadx = 8; 494 | Instrucciones.add(last, gridBagConstraints); 495 | 496 | next.setHorizontalAlignment(SwingConstants.CENTER); 497 | next.setText("Next"); 498 | next.setToolTipText("Siguiente Instruccion"); 499 | next.setBorder(Colors.BORDER); 500 | next.setMaximumSize(dimension_34_19); 501 | next.setMinimumSize(dimension_34_19); 502 | next.setPreferredSize(dimension_34_19); 503 | next.setForeground(Instrucciones.getForeground()); 504 | next.setBackground(Instrucciones.getBackground()); 505 | gridBagConstraints = new GridBagConstraints(); 506 | gridBagConstraints.gridx = 0; 507 | gridBagConstraints.ipadx = 8; 508 | Instrucciones.add(next, gridBagConstraints); 509 | 510 | lastval.setFont(cantarell_15); // NOI18N 511 | lastval.setHorizontalAlignment(SwingConstants.CENTER); 512 | lastval.setForeground(Instrucciones.getForeground()); 513 | lastval.setBackground(Instrucciones.getBackground()); 514 | lastval.setText("-"); 515 | lastval.setBorder(Colors.BORDER); 516 | lastval.setMaximumSize(dimension_192_19); 517 | lastval.setMinimumSize(dimension_192_19); 518 | lastval.setPreferredSize(dimension_192_19); 519 | gridBagConstraints = new GridBagConstraints(); 520 | gridBagConstraints.gridx = 1; 521 | gridBagConstraints.ipadx = 8; 522 | Instrucciones.add(lastval, gridBagConstraints); 523 | 524 | nextval.setFont(cantarell_15); // NOI18N 525 | nextval.setHorizontalAlignment(SwingConstants.CENTER); 526 | nextval.setForeground(Instrucciones.getForeground()); 527 | nextval.setBackground(Instrucciones.getBackground()); 528 | nextval.setText("-"); 529 | nextval.setBorder(Colors.BORDER); 530 | nextval.setMaximumSize(dimension_192_19); 531 | nextval.setMinimumSize(dimension_192_19); 532 | nextval.setPreferredSize(dimension_192_19); 533 | gridBagConstraints = new GridBagConstraints(); 534 | gridBagConstraints.gridx = 1; 535 | gridBagConstraints.ipadx = 8; 536 | Instrucciones.add(nextval, gridBagConstraints); 537 | 538 | conf.setLayout(new GridBagLayout()); 539 | 540 | stepspinner.setModel(new SpinnerNumberModel(assembler.stepsInicio, 0, null, 1)); 541 | stepspinner.setBorder(Colors.BORDER); 542 | stepspinner.setMinimumSize(dimension_100_38); 543 | stepspinner.setPreferredSize(dimension_114_38); 544 | stepspinner.setFont(cantarell_15); 545 | stepspinner.setBackground(conf.getBackground()); 546 | stepspinner.addMouseWheelListener(new MouseWheelListener() { 547 | @Override 548 | public void mouseWheelMoved(MouseWheelEvent e) { 549 | mouseWheelMovedEvent(e); 550 | } 551 | }); 552 | gridBagConstraints = new GridBagConstraints(); 553 | gridBagConstraints.gridx = 1; 554 | conf.add(stepspinner, gridBagConstraints); 555 | 556 | memspinner.setModel(new SpinnerNumberModel(assembler.memAddress, 0, null, 16)); 557 | memspinner.setBorder(Colors.BORDER); 558 | memspinner.setMinimumSize(dimension_100_38); 559 | memspinner.setPreferredSize(dimension_114_38); 560 | memspinner.setFont(cantarell_15); 561 | memspinner.setBackground(conf.getBackground()); 562 | memspinner.addMouseWheelListener(new MouseWheelListener() { 563 | public void mouseWheelMoved(MouseWheelEvent evt) { 564 | mouseWheelMovedEvent(evt); 565 | } 566 | }); 567 | gridBagConstraints = new GridBagConstraints(); 568 | gridBagConstraints.gridx = 1; 569 | conf.add(memspinner, gridBagConstraints); 570 | 571 | membutton.setText("Memoria"); 572 | membutton.setToolTipText("Direccion de Memoria desde la cual mostrar"); 573 | membutton.setBorder(Colors.BORDER); 574 | membutton.setHorizontalTextPosition(SwingConstants.CENTER); 575 | membutton.setMargin(new Insets(0, 0, 0, 0)); 576 | membutton.setMaximumSize(dimension_68_38); 577 | membutton.setMinimumSize(dimension_70_38); 578 | membutton.setPreferredSize(dimension_70_38); 579 | membutton.setFont(cantarell_15); 580 | membutton.addActionListener(new ActionListener() { 581 | public void actionPerformed(ActionEvent evt) { 582 | membuttonActionPerformed(evt); 583 | } 584 | }); 585 | gridBagConstraints = new GridBagConstraints(); 586 | gridBagConstraints.gridx = 0; 587 | gridBagConstraints.gridy = 1; 588 | conf.add(membutton, gridBagConstraints); 589 | 590 | stepbutton.setText("Steps"); 591 | stepbutton.setToolTipText("Instrucciones a Ejecutar"); 592 | stepbutton.setBorder(Colors.BORDER); 593 | stepbutton.setHorizontalTextPosition(SwingConstants.CENTER); 594 | stepbutton.setMargin(new Insets(0, 0, 0, 0)); 595 | stepbutton.setMaximumSize(dimension_68_38); 596 | stepbutton.setMinimumSize(dimension_70_38); 597 | stepbutton.setPreferredSize(dimension_70_38); 598 | stepbutton.setFont(cantarell_15); 599 | stepbutton.addActionListener(new ActionListener() { 600 | public void actionPerformed(ActionEvent evt) { 601 | stepbuttonActionPerformed(evt); 602 | } 603 | }); 604 | gridBagConstraints = new GridBagConstraints(); 605 | gridBagConstraints.gridx = 0; 606 | gridBagConstraints.gridy = 0; 607 | conf.add(stepbutton, gridBagConstraints); 608 | 609 | stdinbutton.setText("Stdin"); 610 | stdinbutton.setBorder(Colors.BORDER); 611 | stdinbutton.setMaximumSize(dimension_68_25); 612 | stdinbutton.setMinimumSize(dimension_68_25); 613 | stdinbutton.setPreferredSize(dimension_68_25); 614 | stdinbutton.setFont(cantarell_15); 615 | stdinbutton.addActionListener(new ActionListener() { 616 | public void actionPerformed(ActionEvent evt) { 617 | stdinbuttonActionPerformed(evt); 618 | } 619 | }); 620 | 621 | stdinval.setText("t 10"); 622 | stdinval.setBorder(Colors.BORDER); 623 | stdinval.setPreferredSize(dimension_73_25); 624 | stdinval.setFont(cantarell_15); 625 | stdinval.setBackground(conf.getBackground()); 626 | stdinval.addKeyListener(new KeyAdapter() { 627 | public void keyPressed(java.awt.event.KeyEvent evt) { 628 | stdinvalKeyEvent(evt); 629 | } 630 | }); 631 | 632 | asciimem.setMaximumSize(dimension_442_187); 633 | 634 | asciiMemPanel.setLayout(new BoxLayout(asciiMemPanel, BoxLayout.Y_AXIS)); 635 | 636 | for (int i = 0; i < 8; i++) { // Filas de memoria ascii 637 | JPanel asciiMemRow = new JPanel(); 638 | asciiMemRows[i] = asciiMemRow; 639 | Dimension size = dimension_179_19; 640 | GridBagLayout layout = new GridBagLayout(); 641 | asciiMemRow.setBackground(asciiMemPanel.getBackground()); 642 | asciiMemRow.setForeground(asciiMemPanel.getForeground()); 643 | asciiMemRow.setBorder(Colors.BORDER); 644 | asciiMemRow.setMaximumSize(size); 645 | asciiMemRow.setMinimumSize(size); 646 | asciiMemRow.setPreferredSize(size); 647 | asciiMemRow.setLayout(layout); 648 | 649 | for (int j = 0; j < 4; j++) { // Columnas de memoria ascii 650 | AsciiLabel label = new AsciiLabel(assembler.mem[i][j]); 651 | asciiMemWords[i][j] = label; 652 | Dimension labelSize = dimension_35_19; 653 | 654 | label.setFont(monospaced_13); // NOI18N 655 | label.setHorizontalAlignment(SwingConstants.CENTER); 656 | label.setForeground(asciiMemRow.getForeground()); 657 | label.setBackground(asciiMemRow.getBackground()); 658 | label.setText("...."); 659 | label.setMaximumSize(labelSize); 660 | label.setMinimumSize(labelSize); 661 | label.setPreferredSize(labelSize); 662 | label.addMouseListener(new MouseAdapter() { 663 | public void mousePressed(MouseEvent evt) { 664 | changeBitmapMouseEvent(evt); 665 | } 666 | }); 667 | gridBagConstraints = new GridBagConstraints(); 668 | gridBagConstraints.ipadx = 8; 669 | asciiMemRow.add(label, gridBagConstraints); 670 | } 671 | gridBagConstraints = new GridBagConstraints(); 672 | gridBagConstraints.gridx = 1; 673 | asciiMemPanel.add(asciiMemRow, gridBagConstraints); 674 | } 675 | 676 | asciimem.addTab("Ascii", asciiMemPanel); 677 | asciimem.setEnabledAt(0, false); 678 | 679 | reloadButton.setText("Reload"); 680 | reloadButton.setToolTipText("Direccion de Memoria desde la cual mostrar"); 681 | reloadButton.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); 682 | reloadButton.setHorizontalTextPosition(SwingConstants.CENTER); 683 | reloadButton.setMargin(new Insets(0, 0, 0, 0)); 684 | reloadButton.setMaximumSize(dimension_70_38); 685 | reloadButton.setMinimumSize(dimension_70_38); 686 | reloadButton.setPreferredSize(dimension_70_38); 687 | reloadButton.setFont(cantarell_15); 688 | reloadButton.addActionListener(new ActionListener() { 689 | public void actionPerformed(ActionEvent evt) { 690 | reloadButtonActionPerformed(evt); 691 | } 692 | }); 693 | 694 | GroupLayout layout = new GroupLayout(getContentPane()); 695 | getContentPane().setLayout(layout); 696 | layout.setHorizontalGroup( 697 | layout.createParallelGroup(GroupLayout.Alignment.LEADING) 698 | .addGroup(layout.createSequentialGroup() 699 | .addGap(24, 24, 24) 700 | .addGroup(layout.createParallelGroup( 701 | GroupLayout.Alignment.LEADING, 702 | false) 703 | .addGroup(layout.createSequentialGroup() 704 | .addComponent(mem, 705 | GroupLayout.PREFERRED_SIZE, 706 | GroupLayout.DEFAULT_SIZE, 707 | GroupLayout.PREFERRED_SIZE) 708 | .addGap(18, 18, 18) 709 | .addComponent(asciimem, 710 | GroupLayout.PREFERRED_SIZE, 711 | GroupLayout.DEFAULT_SIZE, 712 | GroupLayout.PREFERRED_SIZE) 713 | .addGap(18, 18, 18) 714 | .addComponent(reloadButton, 715 | GroupLayout.DEFAULT_SIZE, 716 | GroupLayout.DEFAULT_SIZE, 717 | Short.MAX_VALUE)) 718 | .addGroup(layout.createSequentialGroup() 719 | .addComponent(conf, 720 | GroupLayout.PREFERRED_SIZE, 721 | GroupLayout.DEFAULT_SIZE, 722 | GroupLayout.PREFERRED_SIZE) 723 | .addPreferredGap( 724 | javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 725 | .addGroup(layout.createParallelGroup( 726 | GroupLayout.Alignment.LEADING, 727 | false) 728 | .addGroup(layout.createSequentialGroup() 729 | .addComponent(stdinbutton, 730 | GroupLayout.PREFERRED_SIZE, 731 | GroupLayout.DEFAULT_SIZE, 732 | GroupLayout.PREFERRED_SIZE) 733 | .addGap(0, 0, 0) 734 | .addComponent(stdinval, 735 | GroupLayout.PREFERRED_SIZE, 736 | 174, 737 | GroupLayout.PREFERRED_SIZE)) 738 | .addComponent(Instrucciones, 739 | GroupLayout.PREFERRED_SIZE, 740 | GroupLayout.DEFAULT_SIZE, 741 | GroupLayout.PREFERRED_SIZE))) 742 | .addGroup(layout.createSequentialGroup() 743 | .addGroup(layout.createParallelGroup( 744 | GroupLayout.Alignment.LEADING) 745 | .addGroup(layout.createSequentialGroup() 746 | .addComponent(tabRegistros, 747 | GroupLayout.PREFERRED_SIZE, 748 | GroupLayout.DEFAULT_SIZE, 749 | GroupLayout.PREFERRED_SIZE) 750 | .addGap(18, 18, 18) 751 | .addComponent(asciireg, 752 | GroupLayout.PREFERRED_SIZE, 753 | GroupLayout.DEFAULT_SIZE, 754 | GroupLayout.PREFERRED_SIZE)) 755 | .addComponent(bitTab, 756 | GroupLayout.PREFERRED_SIZE, 757 | GroupLayout.DEFAULT_SIZE, 758 | GroupLayout.PREFERRED_SIZE)) 759 | .addGap(18, 18, 18) 760 | .addComponent(controltab, 761 | GroupLayout.PREFERRED_SIZE, 762 | GroupLayout.DEFAULT_SIZE, 763 | GroupLayout.PREFERRED_SIZE))) 764 | .addContainerGap(GroupLayout.DEFAULT_SIZE, 765 | Short.MAX_VALUE))); 766 | layout.setVerticalGroup( 767 | layout.createParallelGroup(GroupLayout.Alignment.LEADING) 768 | .addGroup(GroupLayout.Alignment.TRAILING, layout 769 | .createSequentialGroup() 770 | .addGap(24, 24, 24) 771 | .addGroup(layout.createParallelGroup( 772 | GroupLayout.Alignment.TRAILING) 773 | .addGroup(layout.createParallelGroup( 774 | GroupLayout.Alignment.LEADING, 775 | false) 776 | .addComponent(asciireg, 777 | GroupLayout.DEFAULT_SIZE, 778 | GroupLayout.DEFAULT_SIZE, 779 | Short.MAX_VALUE) 780 | .addComponent(tabRegistros, 781 | GroupLayout.DEFAULT_SIZE, 782 | GroupLayout.DEFAULT_SIZE, 783 | Short.MAX_VALUE)) 784 | .addComponent(controltab, 785 | GroupLayout.PREFERRED_SIZE, 786 | GroupLayout.DEFAULT_SIZE, 787 | GroupLayout.PREFERRED_SIZE)) 788 | .addGap(18, 18, 18) 789 | .addGroup(layout.createParallelGroup( 790 | GroupLayout.Alignment.LEADING) 791 | .addGroup(layout.createSequentialGroup() 792 | .addComponent(bitTab, 793 | GroupLayout.PREFERRED_SIZE, 794 | GroupLayout.DEFAULT_SIZE, 795 | GroupLayout.PREFERRED_SIZE) 796 | .addGroup(layout.createParallelGroup( 797 | GroupLayout.Alignment.LEADING) 798 | .addGroup(layout.createSequentialGroup() 799 | .addGap(18, 18, 18) 800 | .addComponent(conf, 801 | GroupLayout.PREFERRED_SIZE, 802 | GroupLayout.DEFAULT_SIZE, 803 | GroupLayout.PREFERRED_SIZE)) 804 | .addGroup(layout.createSequentialGroup() 805 | .addGap(18, 18, 18) 806 | .addComponent(Instrucciones, 807 | GroupLayout.PREFERRED_SIZE, 808 | GroupLayout.DEFAULT_SIZE, 809 | GroupLayout.PREFERRED_SIZE) 810 | .addPreferredGap( 811 | javax.swing.LayoutStyle.ComponentPlacement.RELATED, 812 | 16, 813 | Short.MAX_VALUE) 814 | .addGroup(layout.createParallelGroup( 815 | GroupLayout.Alignment.BASELINE) 816 | .addComponent(stdinbutton, 817 | GroupLayout.PREFERRED_SIZE, 818 | GroupLayout.DEFAULT_SIZE, 819 | GroupLayout.PREFERRED_SIZE) 820 | .addComponent(stdinval, 821 | GroupLayout.PREFERRED_SIZE, 822 | GroupLayout.DEFAULT_SIZE, 823 | GroupLayout.PREFERRED_SIZE)))) 824 | .addGap(18, 20, Short.MAX_VALUE) 825 | .addGroup(layout.createParallelGroup( 826 | GroupLayout.Alignment.TRAILING) 827 | .addComponent(mem, 828 | GroupLayout.PREFERRED_SIZE, 829 | GroupLayout.DEFAULT_SIZE, 830 | GroupLayout.PREFERRED_SIZE) 831 | .addComponent(asciimem, 832 | GroupLayout.PREFERRED_SIZE, 833 | GroupLayout.DEFAULT_SIZE, 834 | GroupLayout.PREFERRED_SIZE))) 835 | .addGroup(layout.createSequentialGroup() 836 | .addGap(0, 0, Short.MAX_VALUE) 837 | .addComponent(reloadButton, 838 | GroupLayout.PREFERRED_SIZE, 839 | GroupLayout.DEFAULT_SIZE, 840 | GroupLayout.PREFERRED_SIZE))) 841 | .addGap(24, 24, 24))); 842 | 843 | this.addKeyListener(new KeyAdapter() { 844 | public void keyPressed(KeyEvent evt) { 845 | frameKeyPressEvent(evt); 846 | } 847 | }); 848 | pack(); 849 | 850 | this.update(); 851 | } 852 | 853 | public void frameKeyPressEvent(KeyEvent e) { 854 | switch (e.getKeyCode()) { 855 | case KeyEvent.VK_T: 856 | stepbuttonActionPerformed(null); 857 | break; 858 | case KeyEvent.VK_V: 859 | case KeyEvent.VK_M: 860 | membuttonActionPerformed(null); 861 | break; 862 | case KeyEvent.VK_F5: 863 | reloadButtonActionPerformed(null); 864 | break; 865 | case KeyEvent.VK_W: 866 | stepspinner.setValue(stepspinner.getNextValue()); 867 | break; 868 | case KeyEvent.VK_S: 869 | if ((Integer) stepspinner.getPreviousValue() > 0) { 870 | stepspinner.setValue(stepspinner.getPreviousValue()); 871 | } 872 | break; 873 | case KeyEvent.VK_D: 874 | assembler.step(1); 875 | this.update(); 876 | break; 877 | case KeyEvent.VK_UP: 878 | memspinner.setValue(memspinner.getNextValue()); 879 | break; 880 | case KeyEvent.VK_DOWN: 881 | if ((Integer) memspinner.getPreviousValue() >= 0) { 882 | memspinner.setValue(memspinner.getPreviousValue()); 883 | } 884 | break; 885 | default: 886 | break; 887 | } 888 | } 889 | 890 | public void mouseWheelMovedEvent(MouseWheelEvent e) { 891 | JSpinner spinner = (JSpinner) e.getSource(); 892 | 893 | if (e.getWheelRotation() < 0) { 894 | spinner.setValue(spinner.getNextValue()); 895 | } else if (spinner.getPreviousValue() != null && (Integer) spinner.getPreviousValue() >= 0) { 896 | spinner.setValue(spinner.getPreviousValue()); 897 | } 898 | } 899 | 900 | private void changeBitmapMouseEvent(MouseEvent evt) { 901 | Object source = evt.getSource(); 902 | 903 | if (source instanceof WordLabel) { 904 | assembler.bitMap = ((WordLabel) evt.getSource()).word; 905 | } else if (source instanceof AsciiLabel) { 906 | assembler.bitMap = ((AsciiLabel) evt.getSource()).word; 907 | } 908 | updateBitmap(); 909 | this.requestFocus(); 910 | } 911 | 912 | private void stdinbuttonActionPerformed(ActionEvent evt) { 913 | String command = stdinval.getText(); 914 | if (command.length() > 0) { 915 | stdinval.setText(""); 916 | assembler.write(command); 917 | String s = assembler.read(); 918 | stdoutpane.setText(s); 919 | this.update(); 920 | } 921 | 922 | this.requestFocus(); 923 | } 924 | 925 | private void stdinvalKeyEvent(KeyEvent evt) { 926 | if (evt.getKeyCode() == KeyEvent.VK_ENTER) { 927 | stdinbuttonActionPerformed(null); 928 | } 929 | if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) { 930 | this.requestFocus(); 931 | } 932 | } 933 | 934 | private void stepbuttonActionPerformed(ActionEvent evt) { 935 | int steps = (Integer) stepspinner.getValue(); 936 | assembler.step(steps); 937 | this.update(); 938 | this.requestFocus(); 939 | } 940 | 941 | private void membuttonActionPerformed(ActionEvent evt) { 942 | assembler.memAddress = (Integer) memspinner.getValue(); 943 | this.update(); 944 | this.requestFocus(); 945 | } 946 | 947 | private void reloadButtonActionPerformed(ActionEvent evt) { 948 | 949 | Config cf = App.loadConfig(App.configPath); 950 | 951 | if (cf == null) { 952 | return; 953 | } 954 | 955 | try { 956 | assembler.close(); 957 | } catch (Exception e) { 958 | App.showError("Assembler", "Ha habido un error al cerrar el anterior emulador\n" 959 | + "El emulador seguira siendo el mismo\n" 960 | + "Para reintentar, reinicia el programa\n" 961 | + e.getMessage()); 962 | e.printStackTrace(); 963 | } 964 | 965 | AssemblerProcess newAssembler = App.createAssemblerProcess(cf); 966 | 967 | if (newAssembler == null) { 968 | return; 969 | } 970 | 971 | assembler = App.createAssemblerProcess(cf); 972 | 973 | for (int i = 0; i < 8; i++) { 974 | controlRegs[i].reg = assembler.controlRegs[i]; 975 | controlRegs[i].setText("0"); 976 | controlRegs[i].setBackground(controlpanel.getBackground()); 977 | for (int j = 0; j < 4; j++) { 978 | registerWords[i][j].word = assembler.regs[i][j]; 979 | memWords[i][j].word = assembler.mem[i][j]; 980 | asciiRegWords[i][j].word = assembler.regs[i][j]; 981 | asciiMemWords[i][j].word = assembler.mem[i][j]; 982 | 983 | registerWords[i][j].setText(assembler.regs[i][j].toString()); 984 | memWords[i][j].setText(assembler.mem[i][j].toString()); 985 | asciiRegWords[i][j].setText(asciiRegWords[i][j].toString()); 986 | asciiMemWords[i][j].setText(asciiMemWords[i][j].toString()); 987 | 988 | registerWords[i][j].setBackground(memoria.getBackground()); 989 | memWords[i][j].setBackground(memoria.getBackground()); 990 | asciiRegWords[i][j].setBackground(asciiMemPanel.getBackground()); 991 | asciiMemWords[i][j].setBackground(asciiMemPanel.getBackground()); 992 | } 993 | } 994 | this.update(); 995 | 996 | this.requestFocus(); 997 | } 998 | 999 | private void updateRegs() { 1000 | assembler.updateRegs(); 1001 | 1002 | int cycle = assembler.controlRegs[2].value; 1003 | 1004 | for (int i = 0; i < 8; i++) { 1005 | controlRegs[i].update(cycle); 1006 | 1007 | for (int j = 0; j < 4; j++) { 1008 | registerWords[i][j].update(cycle); 1009 | asciiRegWords[i][j].update(cycle); 1010 | } 1011 | } 1012 | } 1013 | 1014 | private void updateMem() { 1015 | 1016 | assembler.memAddress = (Integer) memspinner.getValue(); 1017 | 1018 | assembler.updateMem(); 1019 | 1020 | int cycle = assembler.controlRegs[2].value; 1021 | 1022 | for (int i = 0; i < 8; i++) { 1023 | memLabels[i].setText(String.format("%4d", assembler.memAddress + i * 16)); 1024 | for (int j = 0; j < 4; j++) { 1025 | memWords[i][j].update(cycle); 1026 | asciiMemWords[i][j].update(cycle); 1027 | } 1028 | } 1029 | } 1030 | 1031 | private void updateBitmap() { 1032 | Word word = assembler.bitMap; 1033 | StringBuilder s = new StringBuilder(); 1034 | StringBuilder reverser = new StringBuilder(); 1035 | for (int i = 3; i >= 0; i--) { 1036 | reverser.append(String.format("%8s", Integer.toBinaryString(word.data[i] & 0xFF)).replace(' ', '0')).reverse(); 1037 | s.append(reverser); 1038 | reverser.setLength(0); 1039 | } 1040 | 1041 | for (int i = 0; i < 32; i++) { 1042 | char c = s.charAt(i); 1043 | bitLabels[i].setText("" + c); 1044 | if (c == '1') { 1045 | bitLabels[i].setBackground(Colors.UNUPDATED); 1046 | } else { 1047 | bitLabels[i].setBackground(Colors.BACKGROUND); 1048 | } 1049 | } 1050 | } 1051 | 1052 | private void updateInst() { 1053 | lastval.setText(assembler.lastCmd); 1054 | nextval.setText(assembler.nextInst); 1055 | } 1056 | 1057 | private void update() { 1058 | updateRegs(); 1059 | updateMem(); 1060 | updateInst(); 1061 | updateBitmap(); 1062 | } 1063 | } 1064 | --------------------------------------------------------------------------------