110,566
社区成员
发帖
与我相关
我的任务
分享
START:
01.[标签:]
02.<指令><空白><操作数>[空白]<换行>
01.START:
02.LDA #65
03.LDX #A000H
04.STA X
05.END START
Dictionary<string, UInt16> labelDict;
UInt16 binaryLength;
UInt16 executionAddress;
enum Registers
{
Unknown = 0,
A = 4,
B = 2,
D = 1,
X = 16,
Y = 8
}
public Form1()
{
InitializeComponent();
labelDict = new Dictionary<string, ushort>();
binaryLength = 0;
executionAddress = 0;
numericUpDown1.Value = 0x200;
}
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "SunnyApril Assembly Files(*.asm)|*.asm";
ofd.DefaultExt = "asm";
ofd.FileName = string.Empty;
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
textBox1.Text = ofd.FileName;
else
textBox1.Clear();
if (textBox1.Text == string.Empty)
return;
labelDict.Clear();
binaryLength = (UInt16)numericUpDown1.Value;
FileInfo fi = new FileInfo(textBox1.Text);
BinaryWriter output;
FileStream fs = new FileStream(
Path.Combine(
fi.DirectoryName,
fi.Name + ".sab"),
FileMode.Create
);
output = new BinaryWriter(fs);
// magic word
output.Write('C');
output.Write('O');
output.Write('N');
output.Write('M');
output.Write('A');
output.Write('J');
output.Write('I');
output.Write('A');
// org
output.Write((UInt16)numericUpDown1.Value);
// scan to ORG and start writing byte-code
output.Seek((int)numericUpDown1.Value, SeekOrigin.Begin);
// parse source code line-by-line
TextReader input = File.OpenText(textBox1.Text);
string line;
while ((line = input.ReadLine()) != null)
{
parse(line.ToUpper(), output);
dealedSize += line.Length;
}
input.Close();
// binary length & execution address (7 magic-word, 2 org before)
output.Seek(10, SeekOrigin.Begin);
output.Write(binaryLength);
output.Write(executionAddress);
output.Close();
fs.Close();
MessageBox.Show("Done!");
private void parse(string line, BinaryWriter output)
{
// eat white spaces and comments
line = cleanLine(line);
if (line.EndsWith(":"))
// label
labelDict.Add(line.TrimEnd(new char[] { ':' }), binaryLength);
else
{
// code
Match m = Regex.Match(line, @"(\w+)\s(.+)");
string opcode = m.Groups[1].Value;
string operand = m.Groups[2].Value;
switch (opcode)
{
case "LDA":
output.Write((byte)0x01);
output.Write(getByteValue(operand));
binaryLength += 2;
break;
case "LDX":
output.Write((byte)0x02);
output.Write(getWordValue(operand));
binaryLength += 3;
break;
case "STA":
output.Write((byte)0x03);
// NOTE: No error handling.
Registers r = (Registers)Enum.Parse(typeof(Registers), operand);
output.Write((byte)r);
binaryLength += 2;
break;
case "END":
output.Write((byte)0x04);
if (labelDict.ContainsKey(operand))
{
output.Write(labelDict[operand]);
binaryLength += 2;
}
binaryLength += 1;
break;
default:
break;
}
}
}
private byte getByteValue(string operand)
{
byte ret = 0;
if (operand.StartsWith("#"))
{
operand = operand.Remove(0, 1);
char last = operand[operand.Length - 1];
if (char.IsLetter(last))
switch (last)
{
case 'H':
// hex
ret = Convert.ToByte(operand.Remove(operand.Length - 1, 1), 16);
break;
case 'O':
// oct
ret = Convert.ToByte(operand.Remove(operand.Length - 1, 1), 8);
break;
case 'B':
// bin
ret = Convert.ToByte(operand.Remove(operand.Length - 1, 1), 2);
break;
case 'D':
// dec
ret = Convert.ToByte(operand.Remove(operand.Length - 1, 1), 10);
break;
}
else
ret = byte.Parse(operand);
}
return ret;
}