using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ASM { public partial class Form1 : Form { enum Opcode { nop = 0, end = 1, mov1 = 2, mov2 = 3, mov4 = 4, mov8 = 5, z2r = 6, r2z = 7, z2char = 8, char2z = 9, add4 = 10, add8 = 11, sub4 = 12, sub8 = 13, mul4 = 14, mul8 = 15, div4 = 16, div8 = 17, mod = 18, and1 = 19, and4 = 20, or1 = 21, or4 = 22, xor1 = 23, xor4 = 24, not1 = 25, not4 = 26, shl = 27, shr = 28, eq1 = 29, eq2 = 30, eq4 = 31, eq8 = 32, lt4 = 33, lt8 = 34, gt4 = 35, gt8 = 36, jmp = 37, jmpc = 38, push1 = 39, push2 = 40, push4 = 41, push8 = 42, pop1 = 43, pop2 = 44, pop4 = 45, pop8 = 46, call = 47, ret = 48, pow = 52, log = 53, sin = 54, cos = 55, tan = 56, asin = 57, acos = 58, atan = 59, rnd = 60, rndi = 61, tick = 62, ticksh = 63, new_ = 64, del = 65, size = 66, doe = 67, debug = 68, exdel = 69, z2str = 70, z2strb = 71, z2strh = 72, r2str = 73, str2z = 74, strb2z = 75, strh2z = 76, str2r = 77, arrcpy = 78, arrcmp = 79, newreader = 80, newwriter = 81, closereader = 82, closewriter = 83, readerlen = 84, read1 = 85, read2 = 86, read4 = 87, read8 = 88, readarray = 89, write1 = 90, write2 = 91, write4 = 92, write8 = 93, writearray = 94, key = 95, left = 96, right = 97, middle = 98, mousedz = 99, mousex = 100, mousey = 101, clear = 102, present = 103, newsurf = 104, surfdx = 105, surfdy = 106, blt = 107, drawline = 108, drawbox = 109, drawrbox = 110, drawellipse = 111, drawtext = 112, newsndbuf = 113, getvolume = 114, setvolume = 115, play = 116, stop = 117, } enum Addressing { Immediate = 0, X = 1, HP = 2, Data = 3, Stack = 4, Heap = 5, } enum TokenType { None = 0, Identifier, Opcode, LabelMark, LabelValue, Comma, Bool, Char, Z, R, X, HP, Data, Stack, Heap, } struct Token { public TokenType Type; public string Value; public Token(TokenType type, string value) { Type = type; Value = value; } } struct Mov { public string LabelMark; // nullにしてもよい public Opcode TheOpcode; public Addressing DestAddressing; public string Dest; public bool SrcIsLabelValue; public Addressing SrcAddressing; public string Src; } struct Other { public string LabelMark; // nullにしてもよい public Opcode TheOpcode; public byte[] Xs; public Other(string labelMark, Opcode theOpcode, byte[] xs) { LabelMark = labelMark; TheOpcode = theOpcode; Xs = xs; } } public Form1() { InitializeComponent(); } private void UIOK_Click(object sender, EventArgs e) { if (UIAsm.Text.Length == 0) return; List<string> asmLines = new List<string>(); // 空の行も含まれる List<List<Token>> tokenLines = new List<List<Token>>(); // 空の行も含まれる List<object> codeLines = new List<object>(); // 空の行も含まれる、MovかOtherを格納する int lastIndex = 0; for (int i = 0; i < UIAsm.Text.Length; i++) { if (UIAsm.Text[i] == '\r' && UIAsm.Text[i + 1] == '\n') { asmLines.Add(UIAsm.Text.Substring(lastIndex, i - lastIndex)); i++; lastIndex = i + 1; } else if (i == UIAsm.Text.Length - 1) { asmLines.Add(UIAsm.Text.Substring(lastIndex, i - lastIndex + 1)); break; } } for (int i = 0; i < asmLines.Count; i++) { tokenLines.Add(new List<Token>()); for (int j = 0; j < asmLines[i].Length; ) { Token? token; try { token = NextToken(asmLines[i], ref j); } catch (Exception) { UIError.Text = "error! (line: " + i.ToString() +")"; return; } if (token == null) break; Token token_ = token.Value; if (token_.Type == TokenType.Identifier) token_ = CheckIdentifier(token_); if (token_.Type == TokenType.LabelMark) if (!CheckLabelMark(token_)) { UIError.Text = "error! (line: " + i.ToString() + ")"; return; } tokenLines[i].Add(token_); } } for (int i = 0; i < tokenLines.Count; i++) { if (tokenLines[i].Count == 0) { codeLines.Add(null); continue; } try { string tLabelMark; if (tokenLines[i][0].Type == TokenType.LabelMark) { if (tokenLines[i].Count < 2) throw new Exception(); tLabelMark = tokenLines[i][0].Value; } else { tLabelMark = null; } if (tokenLines[i][tLabelMark == null ? 0 : 1].Type != TokenType.Opcode) throw new Exception(); if (tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov1" || tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov2" || tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov4" || tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov8") { if (tokenLines[i].Count != (tLabelMark == null ? 4 : 5)) throw new Exception(); if (tokenLines[i][tLabelMark == null ? 2 : 3].Type != TokenType.Comma) throw new Exception(); if (tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.Bool || tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.Char || tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.Z || tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.R || tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.LabelValue) throw new Exception(); if (tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.Bool || tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.Char || tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.Z || tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.R) { if (tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov1") { if (tokenLines[i][tLabelMark == null ? 3 : 4].Type != TokenType.Bool) throw new Exception(); } else if (tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov2") { if (tokenLines[i][tLabelMark == null ? 3 : 4].Type != TokenType.Char) throw new Exception(); } else if (tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov4") { if (tokenLines[i][tLabelMark == null ? 3 : 4].Type != TokenType.Z) throw new Exception(); } else if (tokenLines[i][tLabelMark == null ? 0 : 1].Value == "mov8") { if (tokenLines[i][tLabelMark == null ? 3 : 4].Type != TokenType.R) throw new Exception(); } } if (tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.HP || tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.HP || tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.LabelValue) if (tokenLines[i][tLabelMark == null ? 0 : 1].Value != "mov4") throw new Exception(); if (tokenLines[i][tLabelMark == null ? 1 : 2].Type == TokenType.HP) if (tokenLines[i][tLabelMark == null ? 3 : 4].Type == TokenType.Z) throw new Exception(); // mov4 hp, 123 に対応しない Mov tMov = new Mov(); tMov.LabelMark = tLabelMark; switch (tokenLines[i][tLabelMark == null ? 0 : 1].Value) { case "mov1": tMov.TheOpcode = Opcode.mov1; break; case "mov2": tMov.TheOpcode = Opcode.mov2; break; case "mov4": tMov.TheOpcode = Opcode.mov4; break; case "mov8": tMov.TheOpcode = Opcode.mov8; break; } switch (tokenLines[i][tLabelMark == null ? 1 : 2].Type) { case TokenType.X: tMov.DestAddressing = Addressing.X; break; case TokenType.HP: tMov.DestAddressing = Addressing.HP; break; case TokenType.Data: tMov.DestAddressing = Addressing.Data; break; case TokenType.Stack: tMov.DestAddressing = Addressing.Stack; break; case TokenType.Heap: tMov.DestAddressing = Addressing.Heap; break; } tMov.Dest = tokenLines[i][tLabelMark == null ? 1 : 2].Value; switch (tokenLines[i][tLabelMark == null ? 3 : 4].Type) { case TokenType.LabelValue: tMov.SrcIsLabelValue = true; tMov.SrcAddressing = Addressing.Immediate; break; case TokenType.Bool: tMov.SrcIsLabelValue = false; tMov.SrcAddressing = Addressing.Immediate; break; case TokenType.Char: tMov.SrcIsLab
C#实现的虚拟机的汇编器的完整代码
于 2024-01-11 19:25:52 首次发布