コード例 #1
0
        private static void PushDupPop(int times)
        {
            var compiler = new BytecodeCompiler();

            for (int k = 0; k < times; k++)
            {
                compiler.Push(k);
            }

            compiler.Dup(times);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            DataWord value = new DataWord(times);

            Assert.AreEqual(DataWord.Zero, machine.Stack.Pop());

            for (int k = 0; k < times; k++)
            {
                value = value.Subtract(DataWord.One);
                Assert.AreEqual(value, machine.Stack.Pop());
            }

            Assert.AreEqual(0, machine.Stack.Size);
        }
コード例 #2
0
        public void GreaterThan()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(2);
            compiler.Push(2);
            compiler.GreaterThan();
            compiler.Push(1);
            compiler.Push(0);
            compiler.GreaterThan();
            compiler.Push(0);
            compiler.Push(1);
            compiler.GreaterThan();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(3, stack.Size);
            Assert.AreEqual(DataWord.Zero, stack.ElementAt(2));
            Assert.AreEqual(DataWord.Zero, stack.ElementAt(1));
            Assert.AreEqual(DataWord.One, stack.ElementAt(0));
        }
コード例 #3
0
        public void MOV_Bonanza32()
        {
            var programText = new string[] {
                "section	.text",
                "global _start",
                "_start:",
                "mov  eax, 0x11112222 ; eax = 0x11112222",
                "mov  ax, 0x3333      ; eax = 0x11113333 (works, only low 16 bits changed)",
                "mov  al, 0x44        ; eax = 0x11113344 (works, only low 8 bits changed)",
                "mov  ah, 0x55        ; eax = 0x11115544 (works, only high 8 bits changed)",
                "xor  ah, ah          ; eax = 0x11110044 (works, only high 8 bits cleared)",
                "mov  eax, 0x11112222 ; eax = 0x11112222",
                "xor  al, al          ; eax = 0x11112200 (works, only low 8 bits cleared)",
                "mov  eax, 0x11112222 ; eax = 0x11112222",
                "xor  ax, ax          ; eax = 0x11110000 (works, only low 16 bits cleared)"
            };

            var compiler = new BytecodeCompiler <UInt32>();
            var compiled = compiler.Compile(programText, "UNIT_TEST");

            var agent = new Agent(kernel, compiled.TextSegment, 0);
            var ret   = agent.Tick();

            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11112222, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11113333, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11113344, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11115544, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11110044, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11112222, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11112200, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11112222, agent.ReadExtendedRegister(Register.EAX)); // Program should have terminated on the second tick

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0x11110000, agent.ReadExtendedRegister(Register.EAX)); // Program should have terminated on the second tick
        }
コード例 #4
0
        public void CompileReadKeyboardAsm()
        {
            var compiler       = new BytecodeCompiler <UInt32>();
            var sourceFileName = "./../../../../picovm/asm-src/read-keyboard32.asm";

            Xunit.Assert.True(File.Exists(Path.Combine(System.Environment.CurrentDirectory, sourceFileName)), $"Cannot find file {sourceFileName} for test, current directory: {System.Environment.CurrentDirectory}");
            var compilation = compiler.Compile(sourceFileName);

            Xunit.Assert.Equal(0, compilation.Errors.Count);
        }
コード例 #5
0
        public void CompileHelloWorldLinux64Asm()
        {
            var compiler       = new BytecodeCompiler <UInt64>();
            var sourceFileName = "./../../../../picovm/asm-src/hello-world-linux64.asm";

            Xunit.Assert.True(File.Exists(Path.Combine(System.Environment.CurrentDirectory, sourceFileName)), $"Cannot find file {sourceFileName} for test, current directory: {System.Environment.CurrentDirectory}");
            var compilation = compiler.Compile(Path.Combine(System.Environment.CurrentDirectory, sourceFileName));

            Xunit.Assert.Equal(0, compilation.Errors.Count);
        }
コード例 #6
0
        public void MOV_REG_CON_Overlayed()
        {
            var programText = new string[] {
                "section	.text",
                "global _start",
                "_start:",
                "MOV EAX, 4294967295", // copy the value 11111111111111111111111111111111 into eax
                "MOV AX, 0",           // copy the value 0000000000000000 into ax
                "MOV AH, 170",         // copy the value 10101010 (0xAA) into ah
                "MOV AL, 85",          // copy the value 01010101 (0x55) into al
                "MOV EAX, 0",          // copy the value 11111111111111111111111111111111 into eax
                "END"
            };

            var compiler = new BytecodeCompiler <UInt32>();
            var compiled = compiler.Compile(programText, "UNIT_TEST");

            var agent = new Agent(kernel, compiled.TextSegment, 0);
            var ret   = agent.Tick();

            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0xFFFFFFFF, agent.ReadExtendedRegister(Register.EAX));
            Xunit.Assert.Equal((ushort)0xFFFF, agent.ReadRegister(Register.AX));
            Xunit.Assert.Equal((byte)0xFF, agent.ReadHalfRegister(Register.AH));
            Xunit.Assert.Equal((byte)0xFF, agent.ReadHalfRegister(Register.AL));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0xFFFF0000, agent.ReadExtendedRegister(Register.EAX));
            Xunit.Assert.Equal((uint)0, agent.ReadRegister(Register.AX));
            Xunit.Assert.Equal((uint)0, agent.ReadHalfRegister(Register.AH));
            Xunit.Assert.Equal((uint)0, agent.ReadHalfRegister(Register.AL));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0xFFFFAA00, agent.ReadExtendedRegister(Register.EAX));
            Xunit.Assert.Equal((uint)170, agent.ReadHalfRegister(Register.AH));
            Xunit.Assert.Equal((uint)0, agent.ReadHalfRegister(Register.AL));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0xFFFFAA55, agent.ReadExtendedRegister(Register.EAX));
            Xunit.Assert.Equal((uint)170, agent.ReadHalfRegister(Register.AH));
            Xunit.Assert.Equal((uint)85, agent.ReadHalfRegister(Register.AL));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)0, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.NotNull(ret);
            Xunit.Assert.Equal(0, ret); // Program should have terminated on the second tick
        }
コード例 #7
0
        public void PUSH_POP_Overlayed()
        {
            var programText = new string[] {
                "section	.text",
                "global _start",
                "_start:",
                "PUSH 4294945365", // push the value 1111 1111 1111 1111 1010 1010 0101 0101‬ (FFFF AA55‬) onto the stack
                "POP EAX",         // pop it back into eax
                "PUSH 2863315917", // push the value 1010 1010 1010 1010 1011 1011 1100 1101 (AAAA BBCD‬) onto the stack
                "POP EAX",         // pop it back into eax
                "END"
            };

            var compiler = new BytecodeCompiler <UInt32>();
            var compiled = compiler.Compile(programText, "UNIT_TEST");

            var agent = new Agent(kernel, compiled.TextSegment, 0);

            Xunit.Assert.Equal((uint)65535, agent.StackPointer);
            var ret = agent.Tick();

            // PUSH 4294945365
            Xunit.Assert.Null(ret);
            agent.Dump();
            Xunit.Assert.Equal((uint)(65535 - 4), agent.StackPointer);
            Xunit.Assert.Equal(4294945365, agent.StackPeek32());
            Xunit.Assert.Equal((uint)0, agent.ReadExtendedRegister(Register.EAX));

            // POP EAX #1
            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)(65535), agent.StackPointer);
            Xunit.Assert.Equal((uint)4294945365, agent.ReadExtendedRegister(Register.EAX));

            // PUSH 2863315917
            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)(65535 - 4), agent.StackPointer);
            Xunit.Assert.Equal(2863315917, agent.StackPeek32());
            Xunit.Assert.Equal((uint)4294945365, agent.ReadExtendedRegister(Register.EAX));

            // POP EAX #2
            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((uint)(65535), agent.StackPointer);
            Xunit.Assert.Equal((uint)2863315917, agent.ReadExtendedRegister(Register.EAX));

            // END
            ret = agent.Tick();
            Xunit.Assert.NotNull(ret);
            Xunit.Assert.Equal(0, ret); // Program should have terminated on the second tick
        }
コード例 #8
0
        private static void PushPop(byte[] bytes)
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.CompileAdjust(Bytecodes.Push1, bytes.Length - 1, bytes);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            Assert.AreEqual(1, machine.Stack.Size);
            Assert.AreEqual(new DataWord(bytes), machine.Stack.Pop());
        }
コード例 #9
0
        public void Stop()
        {
            Machine          machine  = new Machine();
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Stop();
            compiler.Push(1);
            compiler.Push(2);
            compiler.Push(3);

            machine.Execute(compiler.ToBytes());

            Assert.AreEqual(0, machine.Stack.Size);
        }
コード例 #10
0
        public void Not()
        {
            DataWord dw1 = new DataWord(new byte[] { 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 });
            DataWord dw2 = new DataWord(new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f });

            var compiler = new BytecodeCompiler();

            compiler.Push(dw1);
            compiler.Not();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            Assert.AreEqual(dw2, machine.Stack.Pop());
        }
コード例 #11
0
        private static Machine PushSwap(int nswap)
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            for (int k = 0; k < 17; k++)
            {
                compiler.Push(k);
            }

            compiler.Swap(nswap);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            return(machine);
        }
コード例 #12
0
        public void StoreAndLoadDataWord()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(257);
            compiler.Push(42);
            compiler.MStore();
            compiler.Push(43);
            compiler.MLoad();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(new DataWord(257 << 8), stack.Pop());
        }
コード例 #13
0
        public void PushPushPopPop()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(1);
            compiler.Push(2);
            compiler.Pop();
            compiler.Pop();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(0, stack.Size);
        }
コード例 #14
0
        public void InvalidTooLargeJump()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(10000);
            compiler.Jump();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(0, stack.Size);
        }
コード例 #15
0
        public void DivideByZero()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(0);
            compiler.Push(6);
            compiler.Divide();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(1, stack.Size);
            Assert.AreEqual(DataWord.Zero, stack.Pop());
        }
コード例 #16
0
        public void MultiplyThreeTwo()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(2);
            compiler.Push(3);
            compiler.Multiply();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(1, stack.Size);
            Assert.AreEqual(new DataWord(6), stack.Pop());
        }
コード例 #17
0
        public void SubtractThreeOne()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(1);
            compiler.Push(3);
            compiler.Subtract();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(1, stack.Size);
            Assert.AreEqual(DataWord.Two, stack.Pop());
        }
コード例 #18
0
ファイル: Agent64Test.cs プロジェクト: seanmcelroy/picovm
        public void MOV_Bonanza64()
        {
            var programText = new string[] {
                "section	.text",
                "global _start",
                "_start:",
                "mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444",
                "mov  eax, 0x55556666         ; actual:   rax = 0x0000000055556666",
                "mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444",
                "mov  ax, 0x7777              ;           rax = 0x1111222233337777 (works!)",
                "mov  rax, 0x1111222233334444 ;           rax = 0x1111222233334444",
                "xor  eax, eax                ; actual:   rax = 0x0000000000000000",
                "                             ; again, it wiped whole register"
            };

            var compiler = new BytecodeCompiler <UInt64>();
            var compiled = compiler.Compile(programText, "UNIT_TEST");

            var agent = new Agent64(kernel, compiled.TextSegment, 0);
            var ret   = agent.Tick();

            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x1111222233334444, agent.ReadR64Register(Register.RAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x0000000055556666, agent.ReadR64Register(Register.RAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x1111222233334444, agent.ReadR64Register(Register.RAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x1111222233337777, agent.ReadR64Register(Register.RAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x1111222233334444, agent.ReadR64Register(Register.RAX));

            ret = agent.Tick();
            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal((ulong)0x0000000000000000, agent.ReadR64Register(Register.RAX));
        }
コード例 #19
0
        public void StoreByte()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(257);
            compiler.Push(42);
            compiler.MStore8();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var memory = machine.Memory;

            Assert.IsNotNull(memory);
            Assert.AreEqual(1, memory.GetByte(new DataWord(42)));
            Assert.AreEqual(0, memory.GetByte(new DataWord(41)));
            Assert.AreEqual(0, memory.GetByte(new DataWord(43)));
        }
コード例 #20
0
        public void JumpPushes()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(9);
            compiler.Jump();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);
            compiler.JumpDest();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(0, stack.Size);
        }
コード例 #21
0
        public void ConditionalJumpWhenTrue()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(1);
            compiler.Push(11);
            compiler.JumpI();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(0, stack.Size);
        }
コード例 #22
0
        public void GetCoinbase()
        {
            Address            coinbase    = new Address();
            ProgramEnvironment environment = ProgramEnvironment.Builder().Coinbase(coinbase).Build();

            var compiler = new BytecodeCompiler();

            compiler.Coinbase();

            Machine machine = new Machine(environment);

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(1, stack.Size);
            Assert.AreEqual(new DataWord(coinbase.Bytes), stack.Pop());
        }
コード例 #23
0
        public void PushesPc()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(1);
            compiler.Push(2);
            compiler.Push(3);
            compiler.Pc();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(4, stack.Size);
            Assert.AreEqual(new DataWord(6), stack.Pop());
            Assert.AreEqual(DataWord.Three, stack.Pop());
            Assert.AreEqual(DataWord.Two, stack.Pop());
            Assert.AreEqual(DataWord.One, stack.Pop());
        }
コード例 #24
0
        public void InvalidTooLargeJump()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(10000);
            compiler.Jump();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);

            Machine machine = new Machine();

            try
            {
                machine.Execute(compiler.ToBytes());
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual("Invalid jump destination", ex.Message);
            }
        }
コード例 #25
0
        public void ConditionalJumpWhenFalse()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(0);
            compiler.Push(11);
            compiler.JumpI();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.AreEqual(3, stack.Size);
            Assert.AreEqual(new DataWord(4), stack.Pop());
            Assert.AreEqual(new DataWord(3), stack.Pop());
            Assert.AreEqual(new DataWord(2), stack.Pop());
        }
コード例 #26
0
        public void StorageStoreLoad()
        {
            BytecodeCompiler compiler = new BytecodeCompiler();

            compiler.Push(1);
            compiler.SLoad();
            compiler.Push(2);
            compiler.Push(3);
            compiler.SStore();
            compiler.Push(3);
            compiler.SLoad();

            Machine machine = new Machine();

            machine.Execute(compiler.ToBytes());

            var stack = machine.Stack;

            Assert.IsNotNull(stack);
            Assert.AreEqual(2, stack.Size);
            Assert.AreEqual(DataWord.Two, stack.Pop());
            Assert.AreEqual(DataWord.Zero, stack.Pop());
        }
コード例 #27
0
        public void JumpWithoutJumpDest()
        {
            var compiler = new BytecodeCompiler();

            compiler.Push(9);
            compiler.Jump();
            compiler.Push(2);
            compiler.Push(3);
            compiler.Push(4);
            compiler.Push(5);

            Machine machine = new Machine();

            try
            {
                machine.Execute(compiler.ToBytes());
                Assert.Fail();
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual("Invalid jump destination", ex.Message);
            }
        }
コード例 #28
0
    static void Main(string[] args)
    {
        var options = new Options();

        if (!CommandLine.Parser.Default.ParseArguments(args, options))
        {
            Environment.Exit(1);
        }

        var compiler = new BytecodeCompiler();
        ExceptionOr <List <int> > result = Safe.Wrapper(compiler).FileToInstructions(options.InputFile);

        if (result.HasFailed())
        {
            Console.Error.WriteLine("Failed to compile the instructions file: {0}", result.GetException().Message);
            Environment.Exit(2);
        }

        if (options.ShowOpcodes)
        {
            foreach (var op in result.GetValue())
            {
                Console.Write("{0} ", op);
            }
            Console.WriteLine();
            return;
        }

        if (options.ShowLayout)
        {
            var bytecode = new Bytecode();
            int address  = 0;

            int length  = result.GetValue().Count;
            var opcodes = result.GetValue();
            int i       = 0;
            while (i < length)
            {
                var insName = bytecode.FindNameByOpcode(opcodes[i]);
                var numArgs = bytecode.GetNumArgs(opcodes[i]);

                Console.Write("{0:0000}:\t{1} ", i, insName);
                i++;
                for (int j = 0; j < numArgs; j++)
                {
                    Console.Write("{0} ", opcodes[i]);
                    i++;
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            return;
        }

        var interpreter = new VM.Interpreter();

        if (options.Debugger != null)
        {
            var monitor = new Monitor();
            monitor.InsertNewLineBefore = true;
            interpreter.SetMonitor(monitor);

            switch (options.Debugger)
            {
            case "tracer":
                interpreter.Attach(new VM.Tracer());
                break;

            case "singlestep":
                interpreter.Attach(new VM.SingleStepDebugger());
                break;

            default:
                Console.Error.WriteLine("\"{0}\" is not a valid debugger. Use: \"tracer\", \"singlestep\"", options.Debugger);
                Environment.Exit(3);
                break;
            }
        }

        var ins = result.GetValue();

        if (ins.Count > 0)
        {
            interpreter.Run(result.GetValue(), 0);
        }
    }
コード例 #29
0
        private NeoChunk Compile(ChunkNode ast)
        {
            var compiler = new BytecodeCompiler(ast);

            return(BuildNeoChunk(compiler.Compile()));
        }
コード例 #30
0
        public void MOV_REG_CON_Simple()
        {
            var programText = new string[] {
                "section	.text",
                "global _start",
                "_start:",
                "   MOV EAX, 4294967295 ; copy the value 11111111111111111111111111111111 into eax",
                "   MOV AX, 0           ; copy the value 0000000000000000 into ax",
                "   MOV AH, 170         ; copy the value 10101010 (0xAA) into ah",
                "   MOV AL, 85          ; copy the value 01010101 (0x55) into al",
                "   MOV EBX, 5          ; copy the value 5 into ebx",
                "   MOV EAX, EBX        ; copy the value in ebx into eax",
                "   PUSH 4              ; push 4 on the stack",
                "   PUSH EAX            ; push eax (5) on the stack",
                "   PUSH 6              ; push 6 on the stack",
                "   POP EBX             ; pop stack (6) into ebx",
                "   POP EBX             ; pop stack (5) into ebx",
                "   POP [EBX]           ; pop stack (4) into [ebx] memory location = 5",
                "   ADD [EBX], 10       ; add 10 to the value in [ebx] which would change 4 to 14",
                "   PUSH [EBX]          ; push [ebx] memory location=5 value=14 onto the stack",
                "END"
            };

            var compiler = new BytecodeCompiler <UInt32>();
            var compiled = compiler.Compile(programText, "UNIT_TEST");

            var agent = new Agent(kernel, compiled.TextSegment, 0);
            var ret   = agent.Tick();

            Xunit.Assert.Null(ret);
            Xunit.Assert.Equal(4294967295, agent.ReadExtendedRegister(Register.EAX));

            ret = agent.Tick();
            Xunit.Assert.Equal(0U, agent.ReadRegister(Register.AX));

            ret = agent.Tick();
            Xunit.Assert.Equal(170, agent.ReadHalfRegister(Register.AH));

            ret = agent.Tick();
            Xunit.Assert.Equal(85, agent.ReadHalfRegister(Register.AL));

            ret = agent.Tick();
            Xunit.Assert.Equal(5U, agent.ReadExtendedRegister(Register.EBX));

            ret = agent.Tick();
            Xunit.Assert.Equal(5U, agent.ReadExtendedRegister(Register.EAX));
            Xunit.Assert.Equal(5U, agent.ReadExtendedRegister(Register.EBX));

            ret = agent.Tick();
            ret = agent.Tick();
            ret = agent.Tick();

            ret = agent.Tick();
            Xunit.Assert.Equal(6U, agent.ReadExtendedRegister(Register.EBX));

            ret = agent.Tick();
            Xunit.Assert.Equal(5U, agent.ReadExtendedRegister(Register.EBX));

            ret = agent.Tick();
            Xunit.Assert.Equal(5U, agent.ReadExtendedRegister(Register.EBX));

            ret = agent.Tick();
            ret = agent.Tick();
            ret = agent.Tick();
            Xunit.Assert.NotNull(ret);
            Xunit.Assert.Equal(0, ret); // Program should have terminated on the second tick
        }