using System;
public class RAM
{
public byte[] memory = new byte[256];
}
public class CPU
{
// ALU OPERATIONS
public byte ExecuteADD(byte regA, byte regB)
{
byte result = (byte)(regA + regB);
if (result < regA)
{
flagRegister |= (byte)flags.carry;
Console.WriteLine("Carry flag set on");
}
else
{
flagRegister &= (byte)~flags.carry;
}
return result;
}
public void ExecuteSHL(byte regA, byte regB)
{
register[regB] = (byte)(register[regA] << 1);
Console.WriteLine($"SHL Result: {register[regB]}");
}
public void ExecuteSHR(byte regA, byte regB)
{
register[regB] = (byte)(register[regA] >> 1);
Console.WriteLine($"SHR Result: {register[regB]}");
}
public void ExecuteNOT(byte regA, byte regB)
{
register[regB] = (byte)(~regA);
Console.WriteLine($"NOT Result: {register[regB]}");
}
public void ExecuteAND(byte regA, byte regB)
{
register[regB] = (byte)(regA & regB);
Console.WriteLine($"AND Result: {register[regB]}");
}
public void ExecuteOR(byte regA, byte regB)
{
register[regB] = (byte)(regA | regB);
Console.WriteLine($"OR Result: {register[regB]}");
}
public void ExecuteXOR(byte regA, byte regB)
{
register[regB] = (byte)(regA ^ regB);
Console.WriteLine($"XOR Result: {register[regB]}");
}
public void ExecuteCMP(byte regA, byte regB)
{
flagRegister = 0;
if (register[regA] > register[regB])
{
flagRegister = (byte)(flagRegister | (byte)flags.greaterThan);
Console.WriteLine("greaterThan flag set on");
}
else if (register[regA] == register[regB])
{
flagRegister = (byte)(flagRegister | (byte)flags.equal);
Console.WriteLine("equal flag set on");
}
else if (register[regA] < register[regB])
{
flagRegister = (byte)(flagRegister | (byte)flags.zero);
Console.WriteLine("zero flag set on");
}
}
//OTHER INSTRUCTIONS
public void ExecuteLD(RAM ram, byte regA, byte regB)
{
register[regB] = ram.memory[register[regA]];
}
public void ExecuteST(RAM ram, byte regA, byte regB)
{
ram.memory[register[regA]] = register[regB];
}
public void ExecuteDATA(RAM ram, byte IR)
{
byte regB = (byte)(IR & 0b00000011);
IAR++;
byte data = ram.memory[IAR];
register[regB] = data;
Console.WriteLine($"Loaded {data} into register {regB}.");
}
public void ExecuteJMPR(byte regB)
{
IAR = register[regB];
}
public void ExecuteJMP(RAM ram, byte IR)
{
byte regB = (byte)(IR & 0b00000011);
IAR++;
IAR = ram.memory[regB];
Console.WriteLine($"Jumping to address: {IAR}");
}
public void ExecuteJMPIF(byte flagBits, byte targetAddress)
{
flagRegister = flagBits;
bool conditionMet = false;
if ((flagBits & 0b1000) != 0 && (flagRegister & (byte)flags.carry) != 0) conditionMet = true;
if ((flagBits & 0b0100) != 0 && (flagRegister & (byte)flags.greaterThan) != 0) conditionMet = true;
if ((flagBits & 0b0010) != 0 && (flagRegister & (byte)flags.equal) != 0) conditionMet = true;
if ((flagBits & 0b0001) != 0 && (flagRegister & (byte)flags.zero) != 0) conditionMet = true;
if (conditionMet)
{
IAR = (byte)(targetAddress - 1); // -1 because the main loop will increment it after
Console.WriteLine($"Condition met. Jumping to {targetAddress}");
}
else
{
Console.WriteLine("Condition not met, no jump.");
}
}
public void ExecuteCLF()
{
flagRegister = 0;
}
public void ExecuteHALT()
{
running = false;
}
public byte[] register = new byte[4];
public byte IAR;
public byte IR;
public byte MAR;
public byte flagRegister;
public enum flags : byte
{
carry = 0b1000,
greaterThan = 0b0100,
equal = 0b0010,
zero = 0b0001
}
public enum aluOp : byte
{
ADD = 0b000,
SHL = 0b001,
SHR = 0b010,
NOT = 0b011,
AND = 0b100,
OR = 0b101,
XOR = 0b110,
CMP = 0b111
}
public enum instructions : byte
{
LD = 0b000,
ST = 0b001,
DATA = 0b010,
JMPR = 0b011,
JMP = 0b100,
JMPIF = 0b101,
CLF = 0b110,
HALT = 0b111
}
bool running = true;
public void Run(RAM ram)
{
while(running)
{
IR = ram.memory[IAR];
bool isALU = (IR & 0b10000000) != 0;
if (isALU)
{
byte aluOperation = (byte)((IR >> 4) & 0b00000111);
byte regA = (byte)((IR >> 2) & 0b00000011);
byte regB = (byte)(IR & 0b00000011);
switch ((aluOp)aluOperation)
{
case aluOp.ADD:
register[regB] = ExecuteADD(register[regA], register[regB]);
Console.WriteLine($"ADD Result: {register[regB]}");
break;
case aluOp.SHL:
ExecuteSHL(regA, regB);
break;
case aluOp.SHR:
ExecuteSHR(regA, regB);
break;
case aluOp.NOT:
ExecuteNOT(regA, regB);
break;
case aluOp.AND:
ExecuteAND(regA, regB);
break;
case aluOp.OR:
ExecuteOR(regA, regB);
break;
case aluOp.XOR:
ExecuteXOR(regA, regB);
break;
case aluOp.CMP:
ExecuteCMP(regA, regB);
break;
}
}
else
{
byte instr = (byte)((IR >> 4) & 0b00000111);
byte regA = (byte)((IR >> 2) & 0b00000011);
byte regB = (byte)(IR & 0b00000011);
switch ((instructions)instr)
{
case instructions.LD:
ExecuteLD(ram, regA, regB);
Console.WriteLine($"LD Result: {register[regB]}");
break;
case instructions.ST:
ExecuteST(ram, regA, regB);
Console.WriteLine($"ST Result: {ram.memory[regA]}");
break;
case instructions.DATA:
ExecuteDATA(ram, IR);
break;
case instructions.JMPR:
ExecuteJMPR(regB);
Console.WriteLine($"Jumped to adress: {regB}");
break;
case instructions.JMP:
ExecuteJMP(ram, IR);
break;
case instructions.JMPIF:
byte flagBits = (byte)(IR & 0b00001111); // Extract the 4 flag bits
byte targetAddress = ram.memory[++IAR]; // Fetch the next byte as the address
ExecuteJMPIF(flagBits, targetAddress);
break;
case instructions.CLF:
ExecuteCLF();
Console.WriteLine("Flags cleared");
break;
case instructions.HALT:
ExecuteHALT();
Console.WriteLine("CPU Halted");
break;
}
}
IAR++;
}
}
}
public class SimulateComputer
{
public static void Main(string[] args)
{
RAM ram = new RAM();
CPU cpu = new CPU();
ram.memory[0] = 0b00100000;
ram.memory[1] = 35;
ram.memory[2] = 0b00100001;
ram.memory[3] = 13;
ram.memory[4] = 0b10000001;
ram.memory[5] = 0b01110000;
cpu.Run(ram);
}
}
Write, Run & Share C# code online using OneCompiler's C# online compiler for free. It's one of the robust, feature-rich online compilers for C# language, running on the latest version 8.0. Getting started with the OneCompiler's C# compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as C# and start coding.
OneCompiler's C# online compiler supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample program which takes name as input and print your name with hello.
using System;
namespace Sample
{
class Test
{
public static void Main(string[] args)
{
string name;
name = Console.ReadLine();
Console.WriteLine("Hello {0} ", name);
}
}
}
C# is a general purpose object-oriented programming language by Microsoft. Though initially it was developed as part of .net but later it was approved by ECMA and ISO standards.
You can use C# to create variety of applications, like web, windows, mobile, console applications and much more using Visual studio.
| Data Type | Description | Range | size |
|---|---|---|---|
| int | To store integers | -2,147,483,648 to 2,147,483,647 | 4 bytes |
| double | to store large floating point numbers with decimals | can store 15 decimal digits | 8 bytes |
| float | to store floating point numbers with decimals | can store upto 7 decimal digits | 4 bytes |
| char | to store single characters | - | 2 bytes |
| string | to stores text | - | 2 bytes per character |
| bool | to stores either true or false | - | 1 bit |
datatype variable-name = value;
When ever you want to perform a set of operations based on a condition or set of few conditions IF-ELSE is used.
if(conditional-expression) {
// code
}
else {
// code
}
You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.
Switch is an alternative to If-Else-If ladder.
switch(conditional-expression) {
case value1:
// code
break; // optional
case value2:
// code
break; // optional
...
default:
// code to be executed when all the above cases are not matched;
}
For loop is used to iterate a set of statements based on a condition.
for(Initialization; Condition; Increment/decrement) {
// code
}
While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.
while(condition) {
// code
}
Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.
do {
// code
} while (condition);
Array is a collection of similar data which is stored in continuous memory addresses. Array values can be fetched using index. Index starts from 0 to size-1.
data-type[] array-name;
Method is a set of statements which gets executed only when they are called. Call the method name in the main function to execute the method.
static void method-name()
{
// code to be executed
}