Execute Computer/Zero: Difference between revisions
Content added Content deleted
(Created Nim solution.) |
No edit summary |
||
Line 135: | Line 135: | ||
400 DATA "LINKED LIST",45,111,69,112,71,0,78,0,171,79,192,46,224,32,0,28,1,0,0,0,6,0,2,26,5,20,3,30,1,22,4,24 |
400 DATA "LINKED LIST",45,111,69,112,71,0,78,0,171,79,192,46,224,32,0,28,1,0,0,0,6,0,2,26,5,20,3,30,1,22,4,24 |
||
500 DATA "PRISONER",0,0,224,0,0,35,157,178,35,93,174,33,127,65,194,32,127,64,192,35,93,33,126,99,</syntaxhighlight> |
500 DATA "PRISONER",0,0,224,0,0,35,157,178,35,93,174,33,127,65,194,32,127,64,192,35,93,33,126,99,</syntaxhighlight> |
||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|SysUtils,StdCtrls}} |
|||
The original version of the virtual machine has a provision of entering user choices in the Prisoner's dilema game. It works allowing the user to enter a number when executing a Stop instruction. There is no simple way to do this with Rosetta Code instructions that the program should return a value when it reaches a Stop instruction. As a result, all the versions displayed in the Rosetta Code examples, simply returns a zero when it reaches the stop instruction. |
|||
<syntaxhighlight lang="Delphi"> |
|||
{structure that holds name of program and code} |
|||
type TProgram = record |
|||
Name, Code: string; |
|||
end; |
|||
{List of programs} |
|||
var ProgList: array [0..4] of TProgram =( |
|||
(Name: 'Two plus two'; Code: 'LDA 3 ADD 4 STP 2 2'), |
|||
(Name: 'Seven times eight'; Code: 'LDA 12 ADD 10 STA 12 LDA 11 SUB 13 STA 11 BRZ 8 JMP 0 LDA 12 STP 8 7 0 1'), |
|||
(Name: 'The Fibonacci sequence'; Code: 'LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0 LDA 14 STP 1 1 0 8 1'), |
|||
(Name: 'Linked list'; Code: 'LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP STA 14 NOP BRZ 11 STA 15 JMP 0 LDA 14 STP LDA 0 0 28 1 0 0 0 6 0 2 26 5 20 3 30 1 22 4 24'), |
|||
(Name: 'Prisoner’s Dilemma'; Code: '0 0 STP NOP LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 0 ADD 30 ADD 3 STA 0 LDA 1 ADD 30 ADD 3 STA 1 JMP 2 0 1 3') |
|||
); |
|||
{Defines opcode function call} |
|||
type TOpProc = function(Opcode: byte): boolean; |
|||
{Defines argument type for opcode} |
|||
type TArgType = (atNone,atAddress,atMemory); |
|||
{Defines Opcode information} |
|||
type TOpcode = record |
|||
OpCode: integer; |
|||
ArgType: TArgType; |
|||
Mnemonic: string[3]; |
|||
Proc: TOpProc; |
|||
end; |
|||
{Simulated memory, program counter and accumulator} |
|||
var Memory: array [0..31] of byte; |
|||
var ProgramCounter: integer; |
|||
var Accumulator: byte; |
|||
{Routines to carry out actions of opcodes} |
|||
function DoNoOp(Operand: byte): boolean; |
|||
{ ($00) = NOP - (no operation)} |
|||
begin |
|||
Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoLDA(Operand: byte): boolean; |
|||
{ ($20) LDA - (load accumulator) - a := memory [xxxxx]} |
|||
begin |
|||
Accumulator:=Memory[Operand]; |
|||
Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoSTA(Operand: byte): boolean; |
|||
{ ($40) STA - (store accumulator) - memory [xxxxx] := a} |
|||
begin |
|||
Memory[Operand]:=Accumulator; |
|||
Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoADD(Operand: byte): boolean; |
|||
{ ($60) ADD - (add) - a := a + memory [xxxxx]} |
|||
begin |
|||
Accumulator:=Accumulator + Memory[Operand]; |
|||
Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoSUB(Operand: byte): boolean; |
|||
{ ($80) SUB - (subtract) - a := a – memory [xxxxx]} |
|||
begin |
|||
Accumulator:=Accumulator - Memory[Operand]; |
|||
Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoBRZ(Operand: byte): boolean; |
|||
{ ($A0) BRZ - (branch on zero) - if a = 0 then goto xxxxx} |
|||
begin |
|||
if Accumulator=0 then ProgramCounter:=Operand |
|||
else Inc(ProgramCounter); |
|||
Result:=True; |
|||
end; |
|||
function DoJMP(Operand: byte): boolean; |
|||
{ ($C0) JMP - (jump) - goto xxxxx} |
|||
begin |
|||
ProgramCounter:=Operand; |
|||
Result:=True; |
|||
end; |
|||
function DoSTP(Operand: byte): boolean; |
|||
{ ($E0) STP - (stop)} |
|||
begin |
|||
Result:=False; |
|||
end; |
|||
{Table of opcodes} |
|||
var OpTable: array [0..7] of TOpcode= ( |
|||
(Opcode: $00; ArgType: atNone; Mnemonic: 'NOP'; Proc: DoNoOp), |
|||
(Opcode: $20; ArgType: atMemory; Mnemonic: 'LDA'; Proc: DoLDA), |
|||
(Opcode: $40; ArgType: atMemory; Mnemonic: 'STA'; Proc: DoSTA), |
|||
(Opcode: $60; ArgType: atMemory; Mnemonic: 'ADD'; Proc: DoADD), |
|||
(Opcode: $80; ArgType: atMemory; Mnemonic: 'SUB'; Proc: DoSUB), |
|||
(Opcode: $A0; ArgType: atAddress; Mnemonic: 'BRZ'; Proc: DoBRZ), |
|||
(Opcode: $C0; ArgType: atAddress; Mnemonic: 'JMP'; Proc: DoJMP), |
|||
(Opcode: $E0; ArgType: atNone; Mnemonic: 'STP'; Proc: DoSTP)); |
|||
procedure ClearMemory; |
|||
{Set all memory locations to zero} |
|||
var I: integer; |
|||
begin |
|||
for I:=0 to High(Memory) do |
|||
Memory[I]:=0; |
|||
end; |
|||
function DecodeMnemonic(NMem: string): TOpcode; |
|||
{Convert 3-char Mnemonic to opcode info} |
|||
var I: integer; |
|||
begin |
|||
for I:=0 to High(OpTable) do |
|||
if NMem=OpTable[I].Mnemonic then |
|||
begin |
|||
Result:=OpTable[I]; |
|||
exit; |
|||
end; |
|||
raise Exception.Create('Opcode Not Found'); |
|||
end; |
|||
procedure AssembleProgram(Prog: string); |
|||
{Convert text source code into machine code and store in memory} |
|||
var Inx,MemInx,IntAtom,T: integer; |
|||
var Atom: string; |
|||
var OC: TOpcode; |
|||
begin |
|||
ClearMemory; |
|||
MemInx:=0; |
|||
Inx:=1; |
|||
while true do |
|||
begin |
|||
{Get one space delimited atom} |
|||
Atom:=ExtractToken(Prog,' ',Inx); |
|||
{exit if end of source code} |
|||
if Atom='' then break; |
|||
{Is the atom text (Mnemonic) or number?} |
|||
if Atom[1] in ['A'..'Z','a'..'z'] then |
|||
begin |
|||
{Convert Mnemonic to opcode info} |
|||
OC:=DecodeMnemonic(Atom); |
|||
{Get machine value of opcode} |
|||
IntAtom:=OC.OpCode; |
|||
{Is operand of of memory or address type?} |
|||
if OC.ArgType in [atMemory,atAddress] then |
|||
begin |
|||
{if so combine opcode and operand} |
|||
Atom:=ExtractToken(Prog,' ',Inx); |
|||
T:=StrToInt(Atom); |
|||
IntAtom:=IntAtom or T; |
|||
end; |
|||
end |
|||
else IntAtom:=StrToInt(Atom); |
|||
{Store machine code in memory} |
|||
Memory[MemInx]:=IntAtom; |
|||
{Point to next memory location} |
|||
Inc(MemInx); |
|||
end; |
|||
end; |
|||
function DecodeOpcode(Inst: byte; var Opcode: TOpcode): boolean; |
|||
{Convert machine instruction to opcode information} |
|||
var I: integer; |
|||
var Op: byte; |
|||
begin |
|||
Result:=True; |
|||
{Get opcode part of instruction} |
|||
Op:=$E0 and Inst; |
|||
{Look for it in table} |
|||
for I:=0 to High(OpTable) do |
|||
if OpTable[I].OpCode=Op then |
|||
begin |
|||
Opcode:=OpTable[I]; |
|||
exit; |
|||
end; |
|||
Result:=False; |
|||
end; |
|||
function ExecuteInstruction(Instruct: byte): boolean; |
|||
{Execute a single instruction} |
|||
var I: integer; |
|||
var Opcode: TOpcode; |
|||
var Operand: byte; |
|||
begin |
|||
if not DecodeOpcode(Instruct,Opcode) then raise Exception.Create('Illegal Opcode'); |
|||
{Separate instruction and operand} |
|||
Operand:=$1F and Instruct; |
|||
{Execute instruction} |
|||
Result:=Opcode.Proc(Operand); |
|||
end; |
|||
procedure DisplayInstruction(Memo: TMemo; PC: integer); |
|||
{Display instruction information} |
|||
var Opcode: TOpcode; |
|||
var Inst,Operand: integer; |
|||
var S: string; |
|||
begin |
|||
Inst:=Memory[PC]; |
|||
if not DecodeOpcode(Inst,Opcode) then raise Exception.Create('Illegal Opcode'); |
|||
Operand:=Inst and $1F; |
|||
S:=IntToStr(PC)+' $'+IntToHex(Inst,2); |
|||
S:=S+' '+Opcode.Mnemonic; |
|||
case Opcode.ArgType of |
|||
atMemory: |
|||
begin |
|||
S:=S+' Mem['+IntToStr(Operand)+']='; |
|||
S:=S+' '+IntToStr(Memory[Operand]); |
|||
end; |
|||
atAddress: S:=S+' '+IntToStr(Operand); |
|||
end; |
|||
Memo.Lines.Add(S); |
|||
end; |
|||
procedure ExecuteProgram(Memo: TMemo; Prog: TProgram); |
|||
{Executed program until stop instruction reached} |
|||
begin |
|||
Memo.Lines.Add(Prog.Name); |
|||
AssembleProgram(Prog.Code); |
|||
ProgramCounter:=0; |
|||
Accumulator:=0; |
|||
repeat |
|||
begin |
|||
DisplayInstruction(Memo,ProgramCounter); |
|||
end |
|||
until not ExecuteInstruction(Memory[ProgramCounter]); |
|||
Memo.Lines.Add('Result='+IntToStr(Accumulator)); |
|||
Memo.Lines.Add(''); |
|||
end; |
|||
procedure ShowComputerZero(Memo: TMemo); |
|||
{Execute and display all five sample programs.} |
|||
begin |
|||
ExecuteProgram(Memo,ProgList[0]); |
|||
ExecuteProgram(Memo,ProgList[1]); |
|||
ExecuteProgram(Memo,ProgList[2]); |
|||
ExecuteProgram(Memo,ProgList[3]); |
|||
ExecuteProgram(Memo,ProgList[4]); |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Two plus two |
|||
0 $23 LDA Mem[3]= 2 |
|||
1 $64 ADD Mem[4]= 2 |
|||
2 $E0 STP |
|||
Result=4 |
|||
Seven times eight |
|||
0 $2C LDA Mem[12]= 0 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 0 |
|||
3 $2B LDA Mem[11]= 7 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 7 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 8 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 8 |
|||
3 $2B LDA Mem[11]= 6 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 6 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 16 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 16 |
|||
3 $2B LDA Mem[11]= 5 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 5 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 24 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 24 |
|||
3 $2B LDA Mem[11]= 4 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 4 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 32 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 32 |
|||
3 $2B LDA Mem[11]= 3 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 3 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 40 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 40 |
|||
3 $2B LDA Mem[11]= 2 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 2 |
|||
6 $A8 BRZ 8 |
|||
7 $C0 JMP 0 |
|||
0 $2C LDA Mem[12]= 48 |
|||
1 $6A ADD Mem[10]= 8 |
|||
2 $4C STA Mem[12]= 48 |
|||
3 $2B LDA Mem[11]= 1 |
|||
4 $8D SUB Mem[13]= 1 |
|||
5 $4B STA Mem[11]= 1 |
|||
6 $A8 BRZ 8 |
|||
8 $2C LDA Mem[12]= 56 |
|||
9 $E0 STP |
|||
Result=56 |
|||
The Fibonacci sequence |
|||
0 $2E LDA Mem[14]= 1 |
|||
1 $4F STA Mem[15]= 0 |
|||
2 $6D ADD Mem[13]= 1 |
|||
3 $4E STA Mem[14]= 1 |
|||
4 $2F LDA Mem[15]= 1 |
|||
5 $4D STA Mem[13]= 1 |
|||
6 $30 LDA Mem[16]= 8 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 8 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 2 |
|||
1 $4F STA Mem[15]= 1 |
|||
2 $6D ADD Mem[13]= 1 |
|||
3 $4E STA Mem[14]= 2 |
|||
4 $2F LDA Mem[15]= 2 |
|||
5 $4D STA Mem[13]= 1 |
|||
6 $30 LDA Mem[16]= 7 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 7 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 3 |
|||
1 $4F STA Mem[15]= 2 |
|||
2 $6D ADD Mem[13]= 2 |
|||
3 $4E STA Mem[14]= 3 |
|||
4 $2F LDA Mem[15]= 3 |
|||
5 $4D STA Mem[13]= 2 |
|||
6 $30 LDA Mem[16]= 6 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 6 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 5 |
|||
1 $4F STA Mem[15]= 3 |
|||
2 $6D ADD Mem[13]= 3 |
|||
3 $4E STA Mem[14]= 5 |
|||
4 $2F LDA Mem[15]= 5 |
|||
5 $4D STA Mem[13]= 3 |
|||
6 $30 LDA Mem[16]= 5 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 5 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 8 |
|||
1 $4F STA Mem[15]= 5 |
|||
2 $6D ADD Mem[13]= 5 |
|||
3 $4E STA Mem[14]= 8 |
|||
4 $2F LDA Mem[15]= 8 |
|||
5 $4D STA Mem[13]= 5 |
|||
6 $30 LDA Mem[16]= 4 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 4 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 13 |
|||
1 $4F STA Mem[15]= 8 |
|||
2 $6D ADD Mem[13]= 8 |
|||
3 $4E STA Mem[14]= 13 |
|||
4 $2F LDA Mem[15]= 13 |
|||
5 $4D STA Mem[13]= 8 |
|||
6 $30 LDA Mem[16]= 3 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 3 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 21 |
|||
1 $4F STA Mem[15]= 13 |
|||
2 $6D ADD Mem[13]= 13 |
|||
3 $4E STA Mem[14]= 21 |
|||
4 $2F LDA Mem[15]= 21 |
|||
5 $4D STA Mem[13]= 13 |
|||
6 $30 LDA Mem[16]= 2 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
9 $50 STA Mem[16]= 2 |
|||
10 $C0 JMP 0 |
|||
0 $2E LDA Mem[14]= 34 |
|||
1 $4F STA Mem[15]= 21 |
|||
2 $6D ADD Mem[13]= 21 |
|||
3 $4E STA Mem[14]= 34 |
|||
4 $2F LDA Mem[15]= 34 |
|||
5 $4D STA Mem[13]= 21 |
|||
6 $30 LDA Mem[16]= 1 |
|||
7 $91 SUB Mem[17]= 1 |
|||
8 $AB BRZ 11 |
|||
11 $2E LDA Mem[14]= 55 |
|||
12 $E0 STP |
|||
Result=55 |
|||
Linked list |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 28 |
|||
2 $45 STA Mem[5]= 0 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 0 |
|||
5 $3C LDA Mem[28]= 1 |
|||
6 $4E STA Mem[14]= 0 |
|||
7 $3D LDA Mem[29]= 22 |
|||
8 $AB BRZ 11 |
|||
9 $4F STA Mem[15]= 28 |
|||
10 $C0 JMP 0 |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 22 |
|||
2 $45 STA Mem[5]= 60 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 61 |
|||
5 $36 LDA Mem[22]= 2 |
|||
6 $4E STA Mem[14]= 1 |
|||
7 $37 LDA Mem[23]= 26 |
|||
8 $AB BRZ 11 |
|||
9 $4F STA Mem[15]= 22 |
|||
10 $C0 JMP 0 |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 26 |
|||
2 $45 STA Mem[5]= 54 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 55 |
|||
5 $3A LDA Mem[26]= 3 |
|||
6 $4E STA Mem[14]= 2 |
|||
7 $3B LDA Mem[27]= 30 |
|||
8 $AB BRZ 11 |
|||
9 $4F STA Mem[15]= 26 |
|||
10 $C0 JMP 0 |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 30 |
|||
2 $45 STA Mem[5]= 58 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 59 |
|||
5 $3E LDA Mem[30]= 4 |
|||
6 $4E STA Mem[14]= 3 |
|||
7 $3F LDA Mem[31]= 24 |
|||
8 $AB BRZ 11 |
|||
9 $4F STA Mem[15]= 30 |
|||
10 $C0 JMP 0 |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 24 |
|||
2 $45 STA Mem[5]= 62 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 63 |
|||
5 $38 LDA Mem[24]= 5 |
|||
6 $4E STA Mem[14]= 4 |
|||
7 $39 LDA Mem[25]= 20 |
|||
8 $AB BRZ 11 |
|||
9 $4F STA Mem[15]= 24 |
|||
10 $C0 JMP 0 |
|||
0 $2D LDA Mem[13]= 32 |
|||
1 $6F ADD Mem[15]= 20 |
|||
2 $45 STA Mem[5]= 56 |
|||
3 $70 ADD Mem[16]= 1 |
|||
4 $47 STA Mem[7]= 57 |
|||
5 $34 LDA Mem[20]= 6 |
|||
6 $4E STA Mem[14]= 5 |
|||
7 $35 LDA Mem[21]= 0 |
|||
8 $AB BRZ 11 |
|||
11 $2E LDA Mem[14]= 6 |
|||
12 $E0 STP |
|||
Result=6 |
|||
Prisoner’s Dilemma |
|||
0 $00 NOP |
|||
1 $00 NOP |
|||
2 $E0 STP |
|||
Result=0 |
|||
Elapsed Time: 611.666 ms. |
|||
</pre> |
|||
=={{header|Forth}}== |
=={{header|Forth}}== |