Initial commit

This commit is contained in:
Pablu23
2024-04-05 14:25:29 +02:00
commit cec16e0a3e
9 changed files with 388 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.vs/VirtualMachine/v17/.suo Normal file

Binary file not shown.

25
VirtualMachine.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualMachine", "VirtualMachine\VirtualMachine.csproj", "{5F593603-C70C-4549-B9A1-B11999057202}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5F593603-C70C-4549-B9A1-B11999057202}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F593603-C70C-4549-B9A1-B11999057202}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F593603-C70C-4549-B9A1-B11999057202}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F593603-C70C-4549-B9A1-B11999057202}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1A5AFBEB-6C94-4FDD-B0A1-4F71128B9246}
EndGlobalSection
EndGlobal

351
VirtualMachine/Program.cs Normal file
View File

@@ -0,0 +1,351 @@
using System.Collections;
using System.Text;
namespace VirtualMachine
{
internal class Program
{
static void Main(string[] args)
{
VirtualMachine vm = new VirtualMachine();
string codeStr = """
mov r0 %0
mov r1 15
mov r2 8
mov r3 25928
mov r4 %1
str r3 r4
mov r3 27756
mov r4 %2
str r3 r4
mov r3 8303
mov r4 %3
str r3 r4
mov r3 28535
mov r4 %4
str r3 r4
mov r3 27762
mov r4 %5
str r3 r4
mov r3 100
mov r4 %6
str r3 r4
sav r5
add r1 r1 r2
cmp r1 r0
jmple r5
str r1 r0
mov r7 %0
mov r8 4
mov r0 0
sav r6
add r7 r7 r8
ldr r9 r7
prn r9
cmp r0 r9
jmpne r6
""";
uint[] code = AssToByteCode(codeStr);
vm.SetMemory(code);
vm.Run();
}
public static uint[] AssToByteCode(string assCode)
{
string[] lines = assCode.Split('\n');
lines = lines.Where(l => !string.IsNullOrWhiteSpace(l)).ToArray();
List<uint> bytes = [];
foreach (string line in lines)
{
var inputs = line.Split(' ');
string opStr = inputs[0];
uint cond = 0;
if (inputs[0].Length > 3)
{
opStr = inputs[0][..3];
string condStr = inputs[0][3..];
if (condStr.Contains('l'))
{
cond |= 0b001_00000000000000000000000000000;
}
if (condStr.Contains('g'))
{
cond |= 0b010_00000000000000000000000000000;
}
if (condStr.Contains("ne"))
{
cond |= 0b011_00000000000000000000000000000;
}
else if (condStr.Contains('e'))
{
cond |= 0b100_00000000000000000000000000000;
}
}
OpCode op = (OpCode)Enum.Parse(typeof(OpCode), opStr);
uint c = cond ^ ((uint)op << 23);
for (int i = 1; i < inputs.Length; i++)
{
if (inputs[i].Contains('r'))
{
string reg = inputs[i].Replace('r', ' ');
uint par = Convert.ToUInt32(reg);
par <<= 19 - 4 * (i - 1);
c ^= par;
}
else if (inputs[i].Contains('%'))
{
string addr = inputs[i].Replace('%', ' ');
uint par = Convert.ToUInt32(addr) * 4 + (uint)lines.Length * 4 + 1;
c ^= par;
}
else
{
uint par = Convert.ToUInt32(inputs[i]);
c ^= par;
}
}
bytes.Add(c);
}
return bytes.ToArray();
}
}
public enum OpCode
{
// Load from memory
ldr = 0,
// Store to memory
str,
add,
sub,
mul,
div,
mov,
cmp,
jmp,
// Save next Address to register
sav,
// Print as ascii
prn
}
public class VirtualMachine
{
private readonly BitArray _conditionFlags = new(3, false);
public bool Equal
{
get { return _conditionFlags[0]; }
private set { _conditionFlags[0] = value; }
}
public bool Greater
{
get { return _conditionFlags[1]; }
private set { _conditionFlags[1] = value; }
}
public bool Less
{
get { return _conditionFlags[2]; }
private set { _conditionFlags[2] = value; }
}
private uint[] _registers { get; set; } = new uint[16];
private int _codeLength = 0;
private byte[] _memory { get; set; } = new byte[2048];
public int ProgramCounter
{
get { return Convert.ToInt32(_registers[15]); }
private set { _registers[15] = Convert.ToUInt32(value); }
}
public void SetMemory(uint[] code)
{
_codeLength = code.Length * 4;
for (int i = 0; i < code.Length; i++)
{
byte[] b = BitConverter.GetBytes(code[i]);
b.CopyTo(_memory, i * 4);
}
}
public void Run()
{
while (_codeLength > ProgramCounter)
{
uint mem = BitConverter.ToUInt32(_memory, ProgramCounter);
OpCode op = GetOpcode(mem);
int par = GetRegister(mem, 0);
int par1 = GetRegister(mem, 1);
int par2 = GetRegister(mem, 2);
ProgramCounter += 4;
if (ConditionSet(mem))
{
switch (op)
{
case OpCode.ldr:
{
int dst = GetRegister(mem, 0);
int addr = GetRegister(mem, 1);
_registers[dst] = BitConverter.ToUInt32(_memory, (int)_registers[addr]);
}
break;
case OpCode.str:
{
int val = GetRegister(mem, 0);
int dst = GetRegister(mem, 1);
byte[] b = BitConverter.GetBytes(_registers[val]);
b.CopyTo(_memory, _registers[dst]);
}
break;
case OpCode.add:
{
int dst = GetRegister(mem, 0);
int reg1 = GetRegister(mem, 1);
int reg2 = GetRegister(mem, 2);
_registers[dst] = _registers[reg1] + _registers[reg2];
}
break;
case OpCode.sub:
{
int dst = GetRegister(mem, 0);
int reg1 = GetRegister(mem, 1);
int reg2 = GetRegister(mem, 2);
_registers[dst] = _registers[reg1] - _registers[reg2];
}
break;
case OpCode.mul:
{
int dst = GetRegister(mem, 0);
int reg1 = GetRegister(mem, 1);
int reg2 = GetRegister(mem, 2);
_registers[dst] = _registers[reg1] * _registers[reg2];
}
break;
case OpCode.div:
{
int dst = GetRegister(mem, 0);
int reg1 = GetRegister(mem, 1);
int reg2 = GetRegister(mem, 2);
_registers[dst] = _registers[reg1] / _registers[reg2];
}
break;
case OpCode.mov:
{
int dst = GetRegister(mem, 0);
int reg = GetRegister(mem, 1);
uint val = GetValue(mem, 1);
//if (reg == 0 && val != 0)
_registers[dst] = val;
//else
// _registers[dst] = _registers[reg];
}
break;
case OpCode.cmp:
{
int reg1 = GetRegister(mem, 0);
int reg2 = GetRegister(mem, 1);
Equal = _registers[reg1] == _registers[reg2];
Greater = _registers[reg1] > _registers[reg2];
Less = _registers[reg1] < _registers[reg2];
}
break;
case OpCode.jmp:
{
int dst = GetRegister(mem, 0);
ProgramCounter = (int)_registers[dst];
}
break;
case OpCode.sav:
{
int dst = GetRegister(mem, 0);
_registers[dst] = (uint)ProgramCounter;
}
break;
case OpCode.prn:
{
int reg = GetRegister(mem, 0);
uint ascii = _registers[reg];
Console.Write(Encoding.ASCII.GetString(BitConverter.GetBytes(ascii)));
}
break;
}
//Console.WriteLine($"{op} {par} {par1} {par2}");
}
}
Console.WriteLine();
}
private static uint GetValue(uint mem, int pos)
{
uint mask = Convert.ToUInt32(Math.Pow(2, 23 - pos * 4)) - 1;
uint tmp = mem & mask;
return tmp;
}
private bool ConditionSet(uint mem)
{
uint tmp = mem >> 29;
uint cond = 0;
if (Equal)
cond += 1 << 2;
if (Greater)
cond += 1 << 1;
if (Less)
cond += 1;
return (cond & tmp) > 0 || tmp == 0;
}
private static int GetRegister(uint mem, int par)
{
uint tmp = mem << 9;
tmp <<= 4 * par;
tmp >>= 32 - 4;
return (int)tmp;
}
private static OpCode GetOpcode(uint mem)
{
return (OpCode)(mem << 3 >> 32 - 6);
}
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
</Project>